Find를 사용하여 파일 이름을 바꾸고 있습니다.
이것은 작동합니다:find . -iname a* -exec bash -c 'x={};mv {} ${x/a/b}' \;
하지만 그렇지 않습니다:
find . -iname a* -exec bash -c "x={};mv {} ${x/a/b}" \;
왜?
Bash에서 실행됩니다.
감사해요
답변1
먼저 다음을 참조하세요.셸에서 "...", '...', $'...' 및 $"..." 따옴표의 차이점은 무엇입니까?
이것은 작동합니다:
find . -iname a* -exec bash -c 'x={};mv {} ${x/a/b}' \;
현재 디렉토리에 로 시작하는 파일 이름이 없고 a
트리의 파일 이름에 공백이나 쉘 특정 문자가 없으면 예, 아마도 작동할 것입니다.
하지만 그렇지 않습니다:
find . -iname a* -exec bash -c "x={};mv {} ${x/a/b}" \;
이 "x={};mv {} ${x/a/b}"
부분은 큰따옴표로 묶여 있으므로 ${...}
명령을 실행하기 전에 쉘이 여기에서 확장됩니다. 결과 문자열 은 셸에서 설정될 가능성이 없으므로 결과 find
문자열만 볼 수 있습니다 .x={};mv {}
$x
첫 번째 항목에서는 작은따옴표가 확장을 방지하므로 find
참조하여 x={};mv {} ${x/a/b}
파일 이름을 바꾸고 {}
실행하도록 요청한 셸에 결과를 전달합니다. 효과가 있을 수도 있습니다.
그러나 여기에는 몇 가지 문제가 있습니다. 첫 번째 것은 인용되지 않았습니다 -iname a*
. 이것은 실행하기 전에 쉘에서 glob을 확장하므로 find
디렉토리에 eg가 포함되어 있으면 실행하는 abcd.txt
것과 asdf.txt
동일합니다 find . -iname abcd.txt asdf.txt
. 첫 번째 파일 이름은 이고 -iname
, 두 번째 파일 이름은 오류입니다.
그런 다음, 예를 들어 트리 어딘가에 있는 파일 이름을 {}
생각해 보십시오 . 셸에서 변경 하고 실행합니다. 그러나 이는 원하는 구문이 아니며 , run 및 명령으로 할당 됩니다 . 이와 같이 코드와 데이터를 혼합하는 것은 작업하기가 거의 불가능합니다. 특히 다음을 포함할 수 있는 파일 이름의 경우 더욱 그렇습니다.foo bar.txt
find
x={};mv {} ${x/a/b}
x=foo bar.txt;mv foo bar.txt ${x/a/b}
foo
x
bar.txt
모든 문자. 이는 또한 foo; echo doing bad things
.
올바른 방법은 파일 이름을 위치 인수로 내부 쉘에 전달하고 스크립트에서 확장자를 참조하는 것입니다.
그래서,
find . -iname "a*" -exec bash -c 'mv "$1" "${1/a/b}"' sh {} \;
바라보다: