パイプラインで名前にスペースを含むファイルを使用する

パイプラインで名前にスペースを含むファイルを使用する

playファイル(スペースを含む)を含むフォルダがありますdamn filefind出力を使用してパイプする場合tar

find play/ -name 'damn*' | tar cf archive.tar -T -

完璧に動作します。これがうまくいくのはなぜですか?出力にfind問題を引き起こす可能性のあるスペースが含まれていますtar。このコマンドを使用するとき:

tar cf archive.tar $(find play/ -name 'damn*')

Bash は次のエラーを表示します。

tar: play/damn: Cannot stat: No such file or directory
tar: file: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

混乱しています。最初の例が機能するのはなぜですか?

答え1

2番目の例では、コマンド置換の出力をトークン化するシェルによって改行文字が削除されます。改行文字はデフォルトで含まれるため、IFSフィールド自体の一部ではなくフィールド区切り文字と見なされます。最初の例では、入力がシェルではなくパイプから出るため、シェルはトークン化を実行できません。

二重引用符で囲まれたコマンド置換("$(find ... )")は単語の区切りが発生するのを防ぎますが、find内部コマンド置換はほとんど常に発生します。悪いそんな思いはしないでください。セキュリティを最大化するには、UnixツールのGNUバージョンにアクセスできる限り、空の区切り文字オ​​プションを使用する必要があります。

find dir/ -name '...' -print0 | tar cf foo.tar --null --no-recursion -T -

答え2

find play/ -name 'damn*'ファイル名のリストが1行に1つずつ生成されます。play/damn file一致する唯一のファイルの場合echo 'play/damn file'

滞在-Tオプションファイル名は改行で区切る必要があります。他のスペースはファイル名の一部と見なされます。これが最初の例が機能する理由です。

使用するとき$(...), コマンドの出力は次のようになります。スペースに分割シェルによって処理された各単語はパラメータになりますtar。したがってplay/damnfile2つのパラメータになり、どちらも既存のファイルではありません。

関連情報