일부 파일이 포함된 디렉토리가 있습니다 .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' -- {} \;