Exec을 사용하면 모든 매개변수를 한 번에 전달 {} +
하거나 다음을 사용하여 하나씩 전달할 수 있습니다.{} \;
이제 모든 이름을 바꾸고 싶다고 가정 해 보겠습니다.JPEG, 이렇게 하는 데에는 문제가 없습니다.
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec mv '{}' '{}'.new \;
그러나 출력을 리디렉션해야 하는 경우 '{}'
리디렉션 후에는 액세스할 수 없습니다.
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec cjpeg -quality 80 '{}' > optimized_'{}' \;
이것은 작동하지 않습니다. for 루프를 사용하고 find를 사용하기 전에 출력을 변수에 저장해야 합니다. 현실을 직시하자, 그것은 번거로운 일이다.
for f in `find . \( -name '*.jpg' -o -name '*.jpeg' \)`; do cjpeg -quality 80 $f > optimized_$f; done;
그럼 더 좋은 방법이 있나요?
답변1
bash -c
명령 에서 사용 find -exec
하고 bash 명령과 함께 위치 인수를 사용할 수 있습니다.
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec bash -c 'cjpeg -quality 80 "$1" > "$(dirname "$1")/optimized_$(basename "$1")"' sh {} \;
{}
이 방법이 제공됩니다 $1
.
sh
{}
여기에 사용된 문자열은 내부 쉘에 "이름"을 알리기 전의 오류 메시지에 사용됩니다. 이에 대해서는 다음에서 더 자세히 논의됩니다.stackoverflow에 대한 이 답변.
답변2
답이 있습니다 (https://unix.stackexchange.com/a/481687/4778), 하지만 그게 이유입니다.
리디렉션 >
, 파이핑 |
및 $
확장은 모두 명령을 실행하기 전에 셸에서 수행됩니다. 따라서 optimized_{}
시작하기 전에 stdout이 로 리디렉션됩니다.find
답변3
현재 쉘이 이를 해석하는 것을 방지하려면 리디렉션이 필요합니다.
그러나 이를 인용하면 명령의 출력이 리디렉션되는 것을 방지할 수도 있습니다.
알려진 해결책은 셸을 호출하는 것입니다.
find . -name '*.jpg' -exec sh -c 'echo "$1" >"$1".new' called_shell '{}' \;
이 경우 리디렉션( >
)은 현재 셸에서 참조되며 호출 셸 내에서 정상적으로 작동합니다. 서브쉘( )에 대한 인수(이름)로 사용됩니다 called_shell
.$0
sh
파일 이름에 접미사를 추가하면 잘 작동하지만 접두사를 사용하면 잘 작동하지 않습니다. 접두사가 작동하도록 하려면 ./
파일 이름 앞의 찾기를 제거 ${1#./}
하고 해당 -execdir
옵션을 사용해야 합니다.
-iname
이 옵션을 사용하여 *.JPG
이름이 지정되거나 다른 변형이 있는 파일 도 포함할 수도 있고 그렇지 않을 수도 있습니다 .*.JpG
find . \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
cjpeg -quality 80 "$1" > optimized_"${1#./}"
' called_shell '{}' \;
for f do … ; done
그리고 끝에 루프( )와 a를 추가하여 파일당 한 번이 아닌 디렉터리당 한 번 셸을 호출 할 수도 있고 그렇지 않을 수도 있습니다 .+
find . \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
for f; do cjpeg -quality 80 "$f" > optimized_"${f#./}"; done
' called_shell '{}' \+
마지막으로 cjpeg
파일에 직접 쓸 수 있으면 리디렉션이 방지됩니다.
find . \( -iname '*.jpg' -o -iname '*.jpeg' \) -execdir sh -c '
for f; do cjpeg -quality 80 "$f" -outfile optimized_"${f#./}"; done
' called_shell '{}' \+
답변4
스크립트 cjq80을 생성합니다:
#!/bin/bash
cjpeg -quality 80 "$1" > "${1%/*}"/optimized_"${1##*/}"
실행 가능하게 만들어라
chmod u+x cjq80
-exec에서 사용하세요.
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec cjq80 '{}' \;