いくつかのファイルを含むディレクトリがあります.flac
。
[test]$ ls
'test file (with $ign & parentheses).flac' 'test file with spaces.flac'
このファイルに対してffmpegテストコマンドを実行したいと思います。これを達成するためにfind
パラメータを使用します。-exec
find ./ -type f -iregex '.*\.flac' -exec sh -c 'ffmtest=$(ffmpeg -v error -i "{}" -f null - 2>&1);if [ -n "$ffmtest" ];then echo -e "{}\n" $ffmtest;fi ' \;
私のコードのいくつかの説明:
find コマンドは.flac
ファイルを探し、テストのために ffmpeg コマンドに名前を渡します。 ffmpeg コマンドはファイルをテストし (最後のリダイレクトのために) エラー文字列を stdout として返すか、エラーが見つからない場合は何も返しません。ffmtest
変数にエラーが含まれている場合は、ffmpegコマンドの後にifステートメントを使用してファイルを印刷します。名前にはエラー名とエラー文字列が含まれます(ファイルにエラーがなければ何も印刷されません)。
私のコードは期待どおりに機能しますが、$
ファイル名に記号と文字が含まれていると失敗するので、上記のテストファイルについて私が得た出力は次のようになります。
[test]$ find ./ -type f -iregex '.*\.flac' -exec sh -c 'ffmtest=$(ffmpeg -v error -i "{}" -f null - 2>&1);if [ -n "$ffmtest" ];then echo -e "{}\n" $ffmtest;fi ' \;
./test file (with & parentheses).flac
./test file (with & parentheses).flac: No such file or directory
$
シンボルのないテストファイルは正しくテストされ、ffmpegはエラーを出力しませんが、名前にシンボルを含むファイルを開くこともできません。 ffmpegの出力とエコーでファイル名が$
解釈され、$
文字で表示されることがわかります。シンボルは変数として扱われます。
それでは、これらの文字を脱出するにはどうすればよいですか?
答え1
find . -type f -iregex '.*\.flac' -exec sh -c '
for file do
ffmtest=$(ffmpeg -v error -i "$file" -f null - 2>&1)
if [ -n "$ffmtest" ]; then
printf "%s\n" "$file" " $ffmtest"
fi
done' sh {} +
いくつかのルール:
{}
(またはその問題の言語ソルバー)に渡されたコードパラメータを含めないでくださいsh
。これはコード挿入の脆弱性に対応します(これも移植不可能です)。あなたの場合はそれほど悪くありません。ただし、ファイル名がある場合は、$(reboot).flac
より深刻な結果をもたらす可能性があります。ここでは、インラインスクリプトのコードではなく拡張のためにできるだけ多くの内容がforに渡されるように、インラインスクリプトの引数に{}
(with)を渡します。+
sh
find
- パラメータ拡張は常にリストコンテキストで引用されます。
- 任意のデータには使用しないでください
echo
。
答え2
文字通りファイル名に置き換えられますので、{}
特に解析されない場所に置いてください。すでに以下を使用しているため、sh -c
パラメータの配置が理想的です。
find ./ -type f -iregex '.*\.flac' -exec sh -c 'ffmtest=$(ffmpeg -v error -i "$1" -f null - 2>&1);if [ -n "$ffmtest" ];then echo -e "$1\n" $ffmtest;fi' -- {} \;