状況は、MP3プレーヤーを持っているということですmpg321
は、ファイルのリストを引数として受け入れます。私は「music」という名前のディレクトリに音楽を保存します。このディレクトリには、さらにいくつかのディレクトリがあります。全部プレイしたいので、
mpg321 $(find /music -iname "*\.mp3")
。問題は、一部のファイル名に空白が含まれていて、プログラムがそれらの名前を小さな部分に分割し、欠落しているファイルについて文句を言うことです。 find
の結果を引用符で囲む
mpg321 "$(find /music -iname "*\.mp3")"
すべてが1つの大きな「ファイル名」になりますが、これは明らかに見つかりません。
どうすればこれを行うことができますか?それが重要であれば、私はbash
を使用していますが、まもなくzsh
に切り替えます。
次のように、findの-print0
または-printf
オプションをxargs
と組み合わせて使用してみてください。
find /music -iname "*\.mp3" -print0 | xargs -0 mpg321
これがどのように機能するかは マニュアルページを見つける で説明されています:
-print0
真;標準出力に完全なファイル名を出力し、その後に(-printが使用する改行文字の代わりに)ヌル文字を出力します。これにより、改行またはその他の種類の空白を含むファイル名が、find出力を処理するプログラムによって正しく解釈されます。このオプションは、xargsの-0オプションに対応します。
find /music -iname "*\.mp3" -exec mpg123 {} +
GNU findでは、 -print0
およびxargs -0
を使用することもできますが、さらに別のツールを学ぶ意味はほとんどありません。-exec ... {} +
構文については、Linuxが-print0
より後に取得したためほとんど言及されていませんが、今は使用しない理由はありません。
Zshまたはbash 4では、これははるかに簡単です。
mpg123 **/*.[Mm][Pp]3
Zshでのみ、(aの一部)パターンで大文字と小文字を区別しないようにできます。
mpg123 (#i)**/*.mp3
Steven's solution が最善だと思いますが、もう1つの方法は、xargsの-I
フラグを使用することです。これにより、コマンドで引数だけでなく、コマンドの最後に引数を追加します)。これを使用して引数を引用できます。
find /music -iname "*\.mp3" | xargs -0 -Ifoo mpg321 "foo"
通常は直接-exec ${tgt_process} \{\} +
を使用するのが最適ですが、needしてファイルまたはストリーム内のファイル名の確実に区切られたリストをfind
から取得するには、何らかの理由で、これを行うことができます:
find -exec sh -c 'printf "///%s///\n" "$@"' -- \{\} +
それから得られるのは、2つのunique文字列です。すべてのファイル名の先頭には文字列\n///
があり、すべてのファイル名の末尾には文字列///\n
があります。これら2つの文字列は、ファイル名に含まれる文字に関係なく、find
の出力の他の場所では発生しません。
さらに、上記の使用法はPOSIXポータブルのベースラインであり、ほぼすべてのUNIXシステムでの動作に依存できます。これは、その便利さにもかかわらず、他の人が推奨するnullバイト区切り文字の使用には当てはまりません。
ただし、これもまた、何らかの理由で-exec
を直接$tgt_process
できない場合にのみ必要です。 1つには、上記の方法でも解析が必要です。たとえば、シェルが引用する各ファイル名が必要な場合は、最初にファイル名のハードクォートがエスケープされていることを確認する必要があります。
find ... + | sed 's|'\''|&"&"&|g;s|///|'\''|g'
これは、構成文字が何であれ、シェルがエスケープしたファイル名の配列を適切に出力します。これで、受信側のアプリケーションがそれを壊さないことを期待する必要があります。
これを行う別の方法は、ファイル名に含まれるすべての特殊文字をエスケープすることです。例えば。:
find /music -iname "*\.mp3" | sed 's!\([] \*\$\/&[]\)!\\\1!g' | xargs mpg321
これは基本的に、適切にエスケープされたファイル名を実行のためにxargsに渡し、問題はありません。