あるファイルを別のファイルにリダイレクトするのはUUOC(catの無駄な使用)ですか?


36

の内容をの内容とfile2一致させたい場合はfile1、明らかに実行するだけcp file1 file2です。

しかし、私が保存したい場合は、すべてについてfile2 除くなど、など、コンテンツ所有者、権限、拡張属性、ACLを、ハードリンクを、そして私が実行したいとは思わないでしょうcp。*その場合、私はちょうどウンチしたいです内容file1file2

次のように実行されるようです。

< file1 > file2

しかし、それは機能しません。 file2何も切り捨てられず、書き込まれません。しかしながら、

cat < file1 > file2

動作します。

最初のバージョンが機能しないことに驚きました。

2番目のバージョンはUUOCですか?単にリダイレクトを使用して、コマンドを呼び出さずにこれを行う方法はありますか?

注:私は、UUOCが真のアンチパターンというよりも重要な点であることを認識しています。

* のようtniles09が発見されたcp 意志をこのケースでは、実際の仕事に。


3
< file1 > file2あなたが望むことをするかどうかはシェルに依存します。
マイケル・ホーマー

13
まあ、それ< ...の無駄な使用です
jwodder

2
アンチパターンは
mikeserv

6
@jwodder-それは真実ではありません。特にあなたがコピーについて話しているとき。ときに何が起こるかを検討file1存在しないか、または他の読めないとあなたがそれを開く< 前に、 >出力が開かれ、その後、あなたが許可したときに何が起こるかを検討しcat、それを開こうとします。
mikeserv

3
@JonathanLeffler zshでは、リダイレクト付きの空のコマンドがcat(デフォルトで)起動し、基本的に2番目のコマンドを実行します。コメントに収まらない以上の詳細については、以下のステファンシャゼラスの回答を参照してください。
マイケルホーマー

回答:


58

cat < file1 > file2UUOCではありません。古典的には、<および>システム・レベルでファイルディスクリプタ重複のないリダイレクトされ対応します。ファイル記述子の複製自体は何もしません(まあ、>リダイレクトはで開くO_TRUNCので、正確には、出力リダイレクトは出力ファイルを切り捨てます)。< >シンボルに混乱させないでください。リダイレクトはデータを移動しません。ファイル記述子を他のファイル記述子に割り当てます。

この場合file1、そのファイル記述子を開いてファイル記述子に割り当て0<file1== 0<file1)、file2そのファイル記述子をファイル記述子に割り当てます1>file2== 1>file2)。

2つのファイル記述子を取得したので、2つの間でデータをシャベルで処理するプロセスが必要catです。それが目的です。


11
たぶんそれは私だけかもしれませんが、この答えの私のお気に入りの部分は「シャベル」という言葉の使用です。:)非常に明確、ありがとう。
ワイルドカード

1
@Wildcard「シャベル」よりも「ポンプ」を好んでいましたが、それでも良い言葉でした。+1
Mehrdad

シャベルが良い言葉なのはなぜですか?
ブバカゾウバ

1
バッファごとにデータがコピーされるときに、ある山から別の山に一度に一杯の土の山をシャベルで削ります。それは良い例えです。
bsd

1
最初の文で、ファイル記述子が複製されていると言います。それらは複製されていますか、または再割り当てされていますか(2番目の段落として、および機能の動作が示すように)?
グレッグベル

17

他の人が指摘しているように、問題の動作はシェルに依存しているためではありません。あなた(OP)が指摘したように、これは少し面白くて、おそらくユーモラスでもありますか?、ある種のトピック。

ただし、GNUシステムでは、最初の前提に別のソリューションがありますcp --no-preserve=all file1 file2。これを試してみてください、それはあなたの記述された状況を満足させると思います(例えばfile2、その属性を変更しないでコンテンツを変更する)。

$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 16 Dec 16 12:21 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Lookout, world!
    Hello, world!
$ cp --no-preserve=all fred fezzik 
$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 14 Dec 16 12:22 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Hello, world!
    Hello, world!

UPDATEは 実際に、私はちょうど私のシステムのことに気づいたcpそれだけではない限り、属性を保持するようだ-aまたは-p指定されています。私はbashシェルとGNU coreutilsを使用しています。毎日何か新しいことを学ぶと思います...


ハードリンクとさまざまな権限を含むテスト結果(ワイルドカードによる):

$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 file2
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the original contents of file2
$ cp file1 file2
$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 file2
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the contents of file1
$ 

いいね ハードリンクとさまざまな権限を含む独自のテストを実行しましたが、正しいと思われます。
ワイルドカード

テスト結果を追加しました。気にしないでください。:) ACLや拡張属性はテストしませんでしたが、inode番号が保持されていることを考えると、それらも99%確実であると確信しています。
ワイルドカード

いいね...まったく気にしない。:-)
tniles

13

ではzsh、シェル< file1 > file2の作品は、シェルがinvokeを行いますcat

リダイレクトのみで構成され、コマンドも割り当てもないコマンドラインの場合、(デフォルトで)唯一のリダイレクトがその場合(デフォルトで)呼び出される場合を除き、zsh呼び出します$NULLCMDcatデフォルトで)。(それは、エミュレートするシェルまたはシェルのように動作する場合を除きます)。<$READNULLCMDpagerzshshcsh

そう:

< file1 > file2

実際にと同じです

cat < file1 > file2

そして

< file1

と同じです

pager < file1

レコードの場合、この構文はksh93では機能しません
fpmurphy

8
< from > to

コマンドがないため機能しません。プロセスなし。シェルは、ファイルを開いて作成し、リダイレクトを配置します(これらのファイルを参照するファイル記述子は、0および1として配置されます:標準入力および標準出力)。ただし、ループを実行して標準入力から読み取り、標準出力に書き込むことはありません。

zshこの「nullコマンド」のケースでユーザー設定可能なコマンドを置き換えることにより、この機能を実現します。コマンドはコマンドラインには表示されませんが、まだ存在しています。プロセスが作成され、同じように機能します。NULLCMDcatデフォルトであるため、< from > to実際にはを意味 cat < from > toしますが、が別の値に設定されていzshない限りNULLCMD、これは「暗黙の猫」コマンドです。

「catの無用な使用」はcat、ファイルから読み取り、データを別のプロセスに送るための媒介として使用される場合に発生します。そのプロセスのファイル記述子は元のファイルに接続されるだけです。

cat残りのコマンドがまだ同じタスクを実行できるように、状況から除去できる場合、それは役に立たない。取り外しできない場合は、役に立たないわけではありません。

# useless, removable:
$ cat archive.tar | tar tf -    #  -->  tar tf archive.tar

# not removable (in POSIX shell):
$ cat > file
abc
[Ctrl-D]

# likewise:
STRING=$(cat file)

A cat交換可能では同じものではありません。たとえば、ファイルを作成cat > fileする代わりに使用できvi fileます。cat同じタスクを達成するために残されたものを使用しながら、それはの削除としてカウントされません。

もしがcatあるだけで、パイプラインのコマンド、そしてもちろん、それを削除することはできません。残っているものの再配置は同等の仕事をしません。

一部のシェルスクリプターはcat、入力オペランドをコマンドラインの左側に近づけることができると考えるために使用します。ただし、リダイレクトはコマンドラインのどこでも可能です。

# If you're so inclined:
# move source archive operand to the left without cat:
$ < archive.tar tar xf - > listing

ところで、f -tar に使用する必要はありません。tar xf -ただtar xです。
dnt

@mikeserv catファイルの作成に関与しているとはどこで言いますか?答えは、シェルがこれを行うことを明確に述べています。どのような問題に> file言及していますか?既存のファイルの長さをゼロに切り詰めたり、そのようなファイルが存在することを確認したりするために、しばしば単独で使用します。この質問は、なぜUUoCの< from > toようcat < from > toに機能しないのかに関するものであり、「なぜこれにcat代わるものではない理由を教えてください」ではありませんcp
カズ

1
@dnt tarテープアーカイバです。多くのtar実装は、デフォルトで最初のテープデバイスで動作します。
ステファンシャゼル

1

< file1 > file2 シェルに依存しているようです。zshでは動作しますが、bashでは動作しません。

編集:偽のステートメントを削除


cp -aジャムの属性ファイルfile1上書き FILE2の属性を。望ましい動作の反対。加えて、マニュアルページを見てもハードリンクで何が起こるかわかりませんが、file2のハードリンクは保存されないと言っても安全だと思います。
ワイルドカード

あなたは正しいです、私は質問を十分に注意深く読みませんでした。
tastytea

1

すべての良い答えに加えて、次をシミュレートすることでUUOCを回避できますcat

awk 1 file1 > file2   # For line-oriented text, not binaries.
dd if=file1 of=file2  # Works for binary files, too.
# many more geeky ways.

これらのコマンドは、プレーンメタデータをコピーしませんcp


確かに、それらには利点がなく、欠点(パフォーマンス、信頼性)しかありませんcat。ここでは、2つのファイル記述子間でデータを突き出すコマンドが必要であり、catそのための最良のコマンドの1つです。Linuxでfifo用pvに使用できるものも参照してくださいsplice()(ただし、fadvise(POSIX_FADV_SEQUENTIAL)GNUのようには機能しませんcat)。
ステファンシャゼル

ddバイナリファイルのコマンドは良いようです...またはcatバイナリファイルでも同様に機能しますか?
ワイルドカード

@Wildcard catはバイナリファイルでも動作します(Unixは通常区別しませんが、awk、grep、wcなど、一部のツールは特に行ごとに動作します... POSIXは最小の最大行長も定義するため、理論的には行指向のツールは、非常に大きな行の処理を拒否する可能性があります。)
ジェンズ

2
@StéphaneChazelasこの回答は、おしゃべりでもありました。シーズンにもかかわらず、一部の人々は楽しみにアレルギーがあるようです(あなたに向けられたものではありません;私はあなたのシェルの専門知識とOpengroupの標準作業を高く評価しています)。
イェンス

sed '' < file1 > file2;-)
デジタル外傷

0

動作する場合は、修正しないでください。

私は使うだろう

cat < file1 > file2

そしてセマ​​ンティクスのPCに負担をかけないでください。

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