catと「>」の違いによるファイルのゼロ化


23

これらの2つのコマンドは、ファイルのゼロ化についてどのような違いがありますか?後者は前者を行うより短い方法ですか?舞台裏で何が起こっていますか?

両方

$ cat /dev/null > file.txt

$ > file.txt 

産出

-rw-r--r--  1 user  wheel  0 May 18 10:33 file.txt

回答:


28

cat /dev/null > file.txt猫の無駄な使用が

基本的にはcat /dev/null単にcat、何も出力しません。はい、動作しますが、必要のない外部プロセスを呼び出す結果となるため、多くの人に嫌われています。
それは一般的であるという理由だけで一般的なものの一つです。

ちょうどを使用して > file.txtでほとんどのシェルで動作しますが、完全に移植可能ではありません。完全に移植性が必要な場合は、次の方法が適しています。

true > file.txt
: > file.txt

両方ともデータ:true出力せず、シェル組み込みコマンドです(cat外部ユーティリティです)。したがって、より軽量で「適切」です。

 

更新:

タイラールが彼のコメントで言及したように、 >| file.txt構文ます。

ほとんどのシェルには、を介して既存のファイルを切り捨てないようにする設定があります>>|代わりに使用する必要があります。これは、実際にを追加するつもりだった場合のヒューマンエラーを防ぐためです>>。で動作をオンにできますset -C

だから、これで、ファイルを切り捨てる最も簡単で、最も適切で、移植可能な方法は次のようになると思います:

:>| file.txt

2
コロンコマンドはPOSIXで定義されています。コマンドライン引数を展開するために存在するのはヌル操作です。
小次郎

3
LOL、「猫虐待」
KM。

2
@kojiro :もPOSIXによって組み込みが義務付けられており、実際には「特別な」組み込みtrueと見なされるという点で異なります。
jw013

2
noclobberを忘れないでください。>| fileより明示的な切り捨てです。
タイラー

1
いいえtrueはビルトインする必要はなく、従来は必要ありませんでした。:Bourneファミリーのすべてのシェルに組み込まれています。:POSIXごとの特別なビルトインです(: > fileたとえばfile、POSIXシェルでの書き込み用に開くことができない場合、シェルを終了します)true。POSIX は、一部のシステムよりも効率的である:可能性についても言及しています。true
ステファンシャゼル

23

移植性に関して:

                      Bourne POSIX  zsh    csh/tcsh  rc/es  fish
> file                Y      Y      N(1)   N(1)      N      N
: > file              N/Y(2) Y(3)   Y      Y(4)      N(5)   N(5)
true > file           Y(5)   Y      Y      Y(5)      Y(5)   Y(5)
cat /dev/null > file  Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
eval > file           Y(3,8) Y(3)   Y      Y(6)      Y      Y
cp /dev/null file (7) Y(5)   Y      Y(5)   Y(5)      Y(5)   Y(5)
printf '' > file      Y(5)   Y      Y      Y(5)      Y(5)   Y

ノート:

  1. in shまたはkshエミュレーションを除き、コマンドを使用しないリダイレクトの場合、zshでは、デフォルトのコマンドが想定されます(stdinリダイレクトのみのページャー、cat、NULLCMDおよびREADNULLCMD変数を使用して調整できるそうでない場合されます。それは同様の機能からインスピレーションを受けています(t)csh
  2. :Unix V7では:、コメントリーダーとnullコマンドの中間で解釈されるため、リダイレクトは最初は実行されませんでした。その後、それらはすべてのビルトインに似ていて、リダイレクトが失敗した場合、シェルを終了します。
  3. :そしてevalリダイレクトが失敗した場合(シェルを終了している、特殊な組み込み関数であることbashのみPOSIXモードでそれを行います)。
  4. 興味深いことに、では(t)csh、それはnullラベル(for goto)を定義しているので、goto ''そこに分岐します。リダイレクトが失敗した場合、シェルを終了します。
  5. ない限り/対応するコマンドがで使用可能な場合$PATH:一般的ではありません; truecatcpおよびprintf一般的です(POSIX)は、それらが必要です)。
  6. リダイレクトが失敗した場合、シェルを終了します。
  7. fileただし、存在しないファイルへのシンボリックリンクの場合、cp GNUのような実装では作成が拒否されます。
  8. ただし、Bourneシェルの初期バージョンは組み込みのリダイレクトをサポートしていませんでした

読みやすさの観点から:

(このセクションは非常に主観的です)

  • > file。それ>は、プロンプトまたはコメントのように見えます。また、それを読むときに尋ねる質問(およびほとんどのシェルが同じことについて不平を言うでしょう)は、正確にどの出力をリダイレクトしていますか?
  • : > file:no-opコマンドとして知られています。したがって、空のファイルを生成するとすぐに読み取られます。ただし、ここでも:簡単に見逃したり、プロンプトとして表示されたりします。
  • true > fileリダイレクションまたはファイルコンテンツに関係するブール値は何ですか?ここで何を意味しますか?私がそれを読んだときに頭に浮かぶ最初のものです。
  • cat /dev/null > fileに連結/dev/nullfileますか? cat多くの場合、まだ意味をなすことができ、ファイルの内容をダンプするコマンドとして見られること:の内容ダンプに空のファイルをfileビット複雑言うための方法のように、cp /dev/null fileまだ理解できます。
  • cp /dev/null file。コピーの内容空のファイルfile。理にかなって、誰かが方法を知られていないがcp、あなたが作るしようとしていると思うかもしれないデフォルトで行うことを意味しているほかのデバイスを。filenull
  • eval > fileまたはeval '' > file。何も実行せず、その出力をにリダイレクトしますfile。私には理にかなっています。それは一般的なイディオムではないことは奇妙です。
  • printf '' > file:明示的にファイルに何も印刷しません。私にとって最も意味のあるもの。

パフォーマンスの観点から

違いは、組み込みのシェルを使用しているかどうかです。そうでない場合、プロセスを分岐し、コマンドをロードして実行する必要があります。

evalすべてのシェルでビルドされることが保証されています。:使用可能な場合はどこでも組み込みです(Bourne / cshが好きです)。trueBourneのようなシェルにのみ組み込まれています。

printfは、ほとんどの最新のBourne風のシェルとに組み込まれていfishます。

cpそしてcat、一般的にビルトインされていません。

cp /dev/null fileのようなものので、シェルのリダイレクト呼び出しません。

find . -exec cp /dev/null {} \;

より効率的になります:

find . -exec sh -c '> "$1"' sh {} \;

(ただし、必ずしも以下とは限りません:

find . -exec sh -c 'for f do : > "$f"; done' sh {} +

)。

個人的に

個人的には: > file、Bourneのようなシェルで使用していますが、最近はBourneのようなシェル以外は使用していません。


どうdd of=file count=0
小次郎

2
@kojiroはdd(少なくともSolaris 10のような)の実装でcount=0は、無視されます。dd if=/dev/null of=fileよりポータブルになります。いずれにせよ、それはシェルから独立しています。
ステファンシャゼル

わかりましたが、それは包含に値するのと同じcp /dev/null fileですよね?
小次郎

2
@kojiro cp /dev/null fileは一般的なイディオムです。私はそれらに限定しています、ポイントはすべての可能な方法をリストすることではありません。
ステファンシャゼル

5

あなたが見たいと思うかもしれませんtruncate、それはまさにそれをします:ファイルを切り捨てます。

例えば:

truncate --size 0 file.txt

これはおそらくを使用するよりも遅いでしょうtrue > file.txt

ただし、私の主なポイントは次のtruncateとおりです。ファイルを切り捨てることを目的としていますが、>を使用するとファイルが切り捨てられるという副作用があります。


2
あなたが言っ0以外の何かにファイルを切り捨てるしたいときに切り捨ては、いいですシェルがさえなくて、あなたがコンテキストがどこ記述することができます:奇妙な文ですtruncateが、どちらも、利用できるようになる>にもunistdCライブラリが利用可能でしょうか?
小次郎

あんまり。おそらく、利用可能なすべてのスクリプトまたはプログラミング言語に対して、よりエレガントなソリューションがあります。
ファビアン

3
truncateFreeBSDユーティリティであり、比較的最近(2008年)GNU coreutilsに追加されました(ただし、--sizeGNUの長いオプションスタイルはGNU固有です)ので、GNUまたはFreeBSD以外のシステムでは利用できません。ポータブルだとは言いません。cp /dev/null fileシェルリダイレクトなしで動作し、より移植性が高くなります。
ステファンシャゼル

さて、その移植性のコメントを削除します。最近のあなたの定義は異なるようですが。
ファビアン

2

答えfile.txtは、それが何であるか、そしてプロセスがそれにどのように書き込むかに少し依存します!

一般的なユースケースを引用します。ログファイルはfile.txt、という名前で成長しており、それをローテーションしたい場合です。

したがって、たとえばにコピーfile.txtしてfile.txt.saveから、切り捨てfile.txtます。

このシナリオでは、IFファイルがで開かれていないanother_process(例:another_process例えば、プログラムロギング何かそのファイルに出力するプログラムすることができる)、そして、あなたの2つの提案は同等で、よく仕事の両方(しかし、第二は、以下のように好まれます最初の「cat / dev / null> file.txt」は無駄なCatの使用であり、/ dev / nullを開いて読み取ります。

しかし、実際の問題は、other_processまだアクティブであり、file.txtへのハンドルが開いている場合です。

次に、other processファイルのオープン方法に応じて、主に2つのケースが発生します。

  • other_process通常の方法で開いた場合、ハンドルは、たとえばオフセット1200バイトで、ファイル内の以前の場所を指し続けます。したがって、次の書き込みはオフセット1200から開始されるため、1200バイトのファイル(およびother_processが書き込んだもの)が1200個のヌル文字で再び作成されます。あなたが望むものではなく、私は推測します。

  • 「追加モード」でother_process開かfile.txtれた場合、書き込みのたびに、ポインタはファイルの最後まで積極的にシークします。したがって、それを切り捨てると、バイト0まで「シーク」され、悪い副作用はありません。これはあなたが望むものです(...通常!)

これは、ファイルを切り捨てるときother_processに、その場所への書き込みがすべて「追加」モードで開かれていることを確認する必要があることに注意してください。それ以外の場合は、それらを停止する必要がありますother_process、して再度開始するこれにより、以前の場所ではなく、ファイルの先頭を指すようになります。

参考文献:/programming//a/16720582/1841533クリーナーの説明のために、とのノーマルとアペンドモードのログとの差の素敵な短い例/programming//a/984761/1841533


2
この回答のほとんどは、実際には質問に関連するものでも、質問に回答するものでもありません。違いcat /dev/null > file> fileされcat /dev/null、それは、ファイルに違いはありません。
jw013

@ jw013:本当だ!しかし、私は質問の機会を利用して、「あなたが欲しいもの/欲しいものではない」情報を再記述したかったのです。それはあまり知られていないので、ログをローテーションしようとしている人を強く攻撃する可能性がありますファイルを切り捨てます)。
オリビエデュラック

1
すべての時間と場所があります。あなたの情報は他のコンテキストで役に立つかもしれませんが、ここには属していない-ログをローテーションしようとする人は誰もこの全く関係のないリダイレクトの質問を見ないので、より適切な場所を見つけるべきです。ここでは、トウモロコシ畑の真ん中にある他の有用なカボチャ植物が雑草と見なされるように、あなたの答えはデジタル雑草に相当します。
jw013

1

私はこれが好きで、頻繁に使用します。それは見た目がきれいで、誰かが誤ってリターンキーを押したようではないからです:

echo -n "" > file.txt

組み込みもする必要がありますか?


3
ファイルをゼロアウトするには多くの方法があります。KMと思います。質問に示されている2つの方法の違いを理解することにのみ興味がありました。
博士

6
多くのecho実装ではサポートされません-n(出力しまう-n<SPC><NL>ここでは。printf '' > file.txt)は、少なくとも現代/ POSIXシステム間(よりポータブルになります。
ステファンChazelas
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.