ファイルの内容を標準出力に出力するコマンド?


28

catこれを実行できることはわかっていますが、その主な目的は、コンテンツを表示するだけでなく連結することです。

また、私は知っているlessmore、私は何かの簡単な(探していないページャだけで、端末にファイルの内容を出力)し、そのようなことがあれば、それは、このために特別に作られています。


1
実際、catを使用するときの99%は、何かを連結するのではなく、ファイルを表示することです。
LatinSuD 14

1
@LatinSuD-100%の時間- cat連結します。
mikeserv 14

@mikeserv:操作を実行するという意味です。通常の言語の使用法は、少なくとも1回は行われることを意味します。空の文字列の「印刷」には、文字の印刷は含まれません。何も印刷していないと言ってもいいでしょう。現在、コンピューティングでa+b+cは2つの追加が実行され、コンピューティングでaは何も追加されません。同様に、実行にcat fは何も連結されません(これが「1つのファイルのシーケンスを連結する」ことだけを意味する場合でも)。
マークヴァンレーウェン14

2
@mikeserv:in + outの意味がわかりません。確かにcatファイルを読み取り、別のファイル(ストリーム)を書き込みますが、それは何かを連結するという意味ではありません。もしあなたが多分それcat fが実際にやっているということを意味するならcat - f、それはただ真実ではありません。
マークヴァンレーベン14

1
@ confused00:cat本当に連結することを意図していました(cat file1 file2両方のファイルを標準出力に連結します)。ただし、副作用として、引数として1つのファイルしかない場合は、その1つのファイルをstdoutに出力します(どこにでも、端末、または何かにリダイレクトされます)。そのため、stdoutに出力するためだけに作成された他のコマンドはcat存在せず、単純に許可されていました。したがって、使用する必要がありますcat
オリビエデュラック14

回答:


37

最も明白なものはcatです。しかし、また見ているheadtail。行毎にファイルを印刷するには、他のシェルutillitiesもありますsedawkgrep。しかし、それらはファイルの内容を変更したり、ファイル内を検索したりするためのものです。

最も効果的なものを推定するためにいくつかのテストを行いました。すべてのトラフを実行してstrace、システムコールが最も少ないものを確認します。私のファイルには1275行あります。

  • awk:1355システムコール
  • cat:51システムコール
  • grep:1337システムコール
  • head:93システムコール
  • tail:130システムコール
  • sed:1378システムコール

ご覧のとおり、catファイルを連結するように設計されていたとしても、最も高速で効果的なものです。sedawkそしてgrepなぜ彼らはより多くのその1275のシステムコールを持っていることを、行毎にファイルを印刷。


8
syscallをカウントすることをお勧めします!
1

1
+1、答えはより正確(猫の意味について)、より完全(代替)、研究済み(syscalls)
オリビエデュラック14

23

catこれを実行できることはわかっていますが、その主な目的は、コンテンツを表示するだけでなく連結することです。

catまさにその目的は、ファイルを読み込んで標準出力に出力することです。


1
しかしcat --help、「FILE(または標準入力)を標準出力に連結する」と述べています。I CONCATENATE何もしたくない
confused00

18
信じられないかもしれませんが、猫はまさにあなたが探しているものです。
2014

5
いいえ、@ confused00、1月の権利。事は-ターミナル標準出力です-分かりますか?やるreadlink /dev/fd/1例えば-標準プロンプトで実行している場合は、そこにあなたのttyの名前を取得する必要があります。したがって、入力を出力に連結することが、あなたが求めていることです。
mikeserv 14

2
@mikeservええ、私はあなたの主張を見て、私は「連結」の意味にあまりにも固定されていたと思います。
confused00 14

3
ロジックは、1つのファイルのコンテンツを印刷することは、1つ以上のファイルのコンテンツを順番に印刷する特別な場合にすぎません。
zwol

10

まず、cat標準出力に書き込みます。これはcat、対話型シェルへのコマンドの一部として入力された場合でも、必ずしも端末ではありません。標準出力がリダイレクトされても端末に何か書き込む必要がある場合、それはそれほど簡単ではありません(どの端末を指定する必要があり、スクリプトからコマンドを実行する場合は端末がない場合もあります)コマンドが単にパイプラインの一部である場合、標準エラー出力を使用(ab)できます。しかし、あなたはcat実際に仕事をすることを示したので、あなたはそのような状況について尋ねていなかったと思います。

標準出力に書き込まれた内容をパイプラインに送信することが目的である場合、使用は猫の役に立たない賞のcat対象となりますcat file | pipelinepipelineパイプラインを表す)はとしてより効率的に実行できるため、<file pipeline。しかし、繰り返しますが、あなたの言葉から、これはあなたの意図ではないと推測します。

だから、あなたが心配していることはそれほど明確ではありません。もしあなたが見つけたらcat入力が長すぎるは、1文字または2文字のエイリアスを定義できます(標準のUnixでは未使用のままの名前がまだいくつかあります)。しかし、それがcat無駄なサイクルを費やしていることを心配しているなら、そうすべきではありません。

null引数を取らず、標準入力(パイプラインのニュートラルオブジェクト)に標準入力をコピーするだけのプログラムがある場合は、で何ができますか<file null。このようなプログラムはありませんが、簡単に記述できますが(1行のmain関数のみを使用するCプログラムでジョブを実行できます)、cat引数なしで呼び出したcat -場合(または明示的に指定したい場合)は、それだけです。

あった場合にはnocatできない場合は正確に一つのファイル名の引数を取るプログラムは、ファイルを開こうとし、それを文句を言うと、そうでない場合は標準出力にファイルからコピーに進み、その後、それはあなたが求めているだけで何だろう。書くのは少しだけ難しいnull、ファイルを開いたり、テストしたり、場合によっては文句を言ったりする主な作業です(細心の注意が必要な場合は、引数が1つしかないテストを含めて、文句を言うこともできます)。しかしcat、ここでも、単一の引数が提供され、まさにそれを行うため、nocatプログラムは必要ありません。

nocatプログラムの作成に成功したら、なぜ単一の引数で停止するのですか?コードをループにラップすることfor(;*argp!=NULL;++argp)は実際にはまったく労力を必要とせず、バイナリに最大2つのマシン命令を追加し、間違った数の引数について文句を言う必要がなくなります(これにより多くの命令が不要になります)。Voilàの原始バージョンcat、連結ファイル。(正直に言うと、引数なしで動作するように少し調整する必要がありますnull。)

もちろん、実際のcatプログラムでは、彼らは常にいくつかの機能を追加しました。しかし、本質はcat、プログラマーにとっても、それを実行するマシンにとっても、「連結」の面ではまったく労力がかからないということです。そのようなプログラムが存在しないことをcat包含nullしてnocat説明するという事実。cat結果がパイプラインに入る場合、単一の引数で使用することは避けてください。ただし、ファイルの内容を端末で表示するためだけに使用される場合は、リンク先のページでも、catいますので、heしないでください。


あなたは、最初の位置ではなく、1つの無効な名前の中でいくつかのファイル名で呼び出すことによってcat、仮想nocat機能の周りの単純なループによって実際に実装されていることをテストすることがcatできます:このファイルが存在しないとすぐに文句を言うのではなく、cat最初の有効なファイル、および無効なファイルについて不平を言います(少なくとも、これは私の猫の動作です)。


7

以下の下でzsh試してみます

<file

これがファイルを印刷する最短の方法だと思います。'hidden' cat(またはmorestdoutが端末の場合)を使用しますが、印刷に使用されるコマンドはREADNULLCMD変数によって制御されます。変数はコマンド名または関数によって安全に直接上書きできます。たとえば、行番号を付けてファイルを印刷するには:

numcat() { nl -s'> ' -w2 - }
READNULLCMD=numcat
<file

5

POSIXはcatを次のように定義します:

cat-ファイルを連結して印刷する

あらすじ

猫[-u] [ファイル...]

記述

catユーティリティは、ファイルを順番に読み取り、その内容を同じ順番で標準出力に書き込むものとします。

したがって、ここでの連結とは、ファイルを順番に読み取ることを意味すると思います


5

これは過去形の質問です。技術的には、ファイルの内容の印刷stdoutは連結の形式であるため、cat意味的に適切です。printf意味的にデータをフォーマットおよび印刷することを意図していることを忘れないでください。Bashは、ファイルからの入力と出力をリダイレクトする構文も提供します。これらの組み合わせにより、これが生成される場合があります。

printf '%s' "$(<file.txt)"

4
特にラウンドアバウトである点を除けば、表示されるコマンドはに相当しません。これcat file.txtは、後続の改行を削除するためです(これを行います$(...))。
マークヴァンレーベン14

+1、いいキャッチ。それを知りませんでした。
ジェームズM.レイ14

3

bashビルトインを使用し、サブプロセスの作成を回避します。

{ while IFS='' read -rd '' _bcat_; do printf '%s\0' "${_bcat_}"; done; printf '%s' "${_bcat_}"; unset _bcat_; } <'/path/to/file'

IFSreadコマンドにのみ適用されるため、グローバルなIFS変更を心配する必要はありません。

null文字を処理するために必要なループ(StéphaneChazelasに感謝)。

この方法は、ファイルコンテンツが最初に変数(メモリ)に読み込まれるため、大きなファイルには適していません。ところで、私はこの方法で39Mのテキストファイルを印刷しようとしましたが、bashのメモリ使用量は5Mを超えなかったため、このケースについてはわかりません。

また、処理速度が遅く、CPUの効率も低下します。同じ39Mファイルの場合、シングルコアを100%使用すると、約3分かかりました。

大きなファイルまたはバイナリを使用するcat '/path/to/file'か、dd if='/path/to/file' bs=1M可能であれば使用します。


1
またpv -q、Linuxで使用できるsplice()stdin / stdoutのタイプによっては、パフォーマンスを改善できるものも参照してください。
ステファンシャゼラス

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.