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

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

私が望むものfile2の内容と一致すれば、file1明らかに実行できますcp file1 file2

しかし、私が守りたいならすべて~についてfile2 とは別にコンテンツ - 所有者、権限、拡張属性、ACL、ハードリンクなどを実行したくありません。cp*この場合は。file1file2

次はこのトリックを実行するようです。

< file1 > file2

しかし、これはうまくいきません。 file2null に切り捨てられ、記録されません。しかし、

cat < file1 > file2

する働く

驚いたことに、最初のバージョンは動作しませんでした。

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

注:私はUUOCが実際のアンチパターンではなく、賢明な意見に近いことを知っています。

*ようにtniles09発見cp 〜するこの場合は実際に動作します。

答え1

cat < file1 > file2UUOCではありません。通常、システムレベルのファイル記述子の複製に対応するリダイレクトが<行われます。>ファイル記述子の複製自体は何もしません(まあ、>リダイレクトはopenを使用するので、O_TRUNC正確に言えば、出力リダイレクトは出力ファイルを切り捨てます)。この< >記号を混同しないでください。リダイレクトはデータを移動しませんが、ファイル記述子を別のファイル記述子に割り当てます。

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

2 つのファイル記述子があるので、2 つのファイル記述子間でデータを移動するプロセスが必要です。これがまさに目的ですcat

答え2

他の人が指摘したように、問題の動作はシェルによって異なるため、そうではありません。あなた(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!

修正する 実際、または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
$ 

答え3

zshアクションシェルでは、< file1 > file2シェルはを呼び出しますcat

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

だから:

< file1 > file2

実は同じ

cat < file1 > file2

そして

< file1

同じですか?

pager < file1

答え4

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

編集:間違った文を削除しました。

関連情報