web-dev-qa-db-ja.com

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

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

ただし、file2以外についてすべてを保持したい場合は、コンテンツ(所有者、権限、拡張属性、ACL)を除きます、ハードリンクなどの場合、cp。*を実行したくありません。その場合は、file1の内容をfile2にプロップします。

次のようにしてください:

< file1 > file2

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

cat < file1 > file2

は動作します

最初のバージョンが動かないのには驚きました。

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

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

*tniles09が発見した のように、cpは実際にはこの場合に機能します

36
Wildcard

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

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

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

58
PSkocik

他の人が指摘しているように、問題の動作はシェルに依存しているため、そうではありません。あなた(OP)が指摘したように、これは少し pedantic であり、多分 hum​​orous? のトピックです。

ただし、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
$ 
17
tniles

zsh< file1 > file2が機能するシェルでは、シェルはcatを呼び出します。

リダイレクトのみで構成され、コマンドも割り当てもないコマンドラインの場合、リダイレクトが$NULLCMDである場合を除き、zsh<(デフォルトではcat)を呼び出します。代わりに$READNULLCMD(デフォルトではpager)が呼び出されます。 (これは、zshshまたはcshエミュレーションに含まれていない限り、エミュレーションするシェルのように動作します)。

そう:

< file1 > file2

実際には同じです

cat < file1 > file2

そして

< file1

と同じです

pager < file1
13
< from > to

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

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

「猫の無用な使用」は、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)

cat、つまり置換可能は同じものではありません。たとえば、cat > fileの代わりに、vi fileを使用してファイルを作成できます。これは、catの削除としてはカウントされませんが、残っているものを使用して同じタスクを実行します。

catがパイプラインのonlyコマンドの場合、もちろん削除できません。残っているものを再配置しても、同等の処理は行われません。

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

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

すべての良い答えに加えて、simulating a catによってUUOCを回避できます。

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の場合のように、ファイルメタデータをコピーしません。

1
Jens

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

編集:削除されたfalseステートメント

1
tastytea

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

私は使うだろう

cat < file1 > file2

セマンティクスのPCに汗を流さないでください。

0
krazykyngekorny