Bash: コマンド置換における引用

Bash: コマンド置換における引用

つまり、コマンドによってリストされたディレクトリをコマンド内で使用したいのですfind

find $(produces_dir_names --options...) -find-options...

問題はディレクトリ名に空白があることです。生成コマンドの出力で空白を引用符で囲めば十分だと思いました (これは変更できます)。

"a" "a b" "a b c"

しかし、bash は次のように文句を言います:

find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory

ご覧のとおり、see はbash引用符があっても、コマンドの出力をスペースで分割します。 をいじって に設定しようとしましたIFS\n、理解が不十分でうまく動作しないようです。

私が見つけた唯一の回避策は、この Stack Overflow の質問にありました: bash コマンド置換引用符の削除つまり、evalその前に を置くのですが、これはちょっと見苦しいようです。

私の質問:

簡単な方法はありますか? また、 を使用せずにこの置換を記述するとどのようになりますかeval?

引用符は本当に必要ですか?

例(同じ出力を生成):

find $(echo '"a" "a b" "a b c"')

答え1

たぶん2行で

IFS=$'\n' DIRS=( $(produces_dir_names --options...) ) 
find "${DIRS[@]}" -find-options...

例:

$ mkdir -p "/tmp/test/a b/foo" "/tmp/test/x y/bar"

$ IFS=$'\n' DIRS=( $(printf "/tmp/test/a b\n/tmp/test/x y\n") )
$ find "${DIRS[@]}" -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar

しかし、一般的にこれは良いスタイルではありません。たとえば、DIRS に改行が含まれている場合は問題が発生します。null バイトで終了する文字列を出力するように "produces_dir_names" を修正した方がよいでしょう。私の例では、次のようになります。

$ printf "/tmp/test/a b\0/tmp/test/x y\0" | xargs -0 -I '{}' find '{}' -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar

「produces_dir_names」を修正できない場合、私の最後のコメントに関して、最も一般的な解決策は次のようになります。

produces_dir_names --options... | tr '\n' '\0' | xargs -0  -I '{}' find '{}' -find-options...

回避するために「produces_dir_names」を修正しない限り、「改行」の問題は依然として残りますtr

答え2

rudimeier の回答produces_dir_names は良いです — 特に、ヌル終端文字列を印刷するように変更する部分— しかし、彼の回答からはfind、ディレクトリごとに1回実行されることは明らかではないかもしれません。これが十分であれば、それで結構です。しかし、もちろん、find 複数の開始点で呼び出すことも可能です。たとえば、

探す  ディレクトリ1ディレクトリ2ディレクトリ3  -検索オプション...

質問から、それがあなたが望んでいることであることがわかります。これは次のように実行できます。

printf "a\0a b\0a b c" | xargs -0 sh -c '"$@" を検索 -検索オプション...' シュ

これにより、コマンドにすべてのディレクトリ名が追加された状態で が 1 回xargs呼び出されます。その後、シェルはそれらのディレクトリ名のリストを展開します。sh -c"$@"

PS produces_dir_names1 つのコマンド ラインに入力するにはディレクトリ名が多すぎる場合は、xargs強制的にいくつかのコマンドが生成されます。生成されているxargs --verboseコマンドを確認するには、を使用しますxargs

答え3

表示されるエラー メッセージの謎を解くために:

find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory

答えはBashの引用符削除では、結果としてコマンド置換から。

からLESS='+/^ *Quote Removal' man bash

Quote Removal
    After the preceding expansions, all unquoted occurrences of the charac-
    ters  \,  ', and " that did not result from one of the above expansions
    are removed.

参照される「以前の拡張」には次のものが含まれます。

EXPANSION
   Brace Expansion
   Tilde Expansion
   Parameter Expansion
   Command Substitution
   Arithmetic Expansion
   Process Substitution
   Word Splitting
   Pathname Expansion
   Quote Removal

関連情報