명령 find
명령을 사용하여 여러 파일 (file1 … filen을 file1_renamed … filen_renamed)의 이름을 바꾸고 싶습니다 .
find . -type f -name 'file*' -exec mv filename='{}' $(basename $filename)_renamed ';'
그러나이 오류가 발생합니다.
mv: cannot stat ‘filename=./file1’: No such file or directory
filename이 쉘 변수로 해석되지 않기 때문에 작동하지 않습니다.
답변
다음은 접근 방식을 직접 수정 한 것입니다.
find . -type f -name 'file*' -exec sh -c 'x="{}"; mv "$x" "${x}_renamed"' \;
그러나 일치하는 파일이 많은 경우 mv
각 일치 항목에 대해 새 셸 (을 실행 )을 시작하므로 비용이 많이 듭니다 . 파일 이름에 재미있는 문자가 있으면 폭발합니다. 보다 효율적이고 안전한 접근 방식은 다음과 같습니다.
find . -type f -name 'file*' -print0 | xargs --null -I{} mv {} {}_renamed
또한 이상한 이름의 파일로 작업하는 이점도 있습니다. 경우 find
지원을, 이것은 줄일 수있다
find . -type f -name 'file*' -exec mv {} {}_renamed \;
xargs
사용하지 않을 경우 버전에 유용 {}
같이,
find .... -print0 | xargs --null rm
여기 rm
에서 한 번 (또는 여러 파일로 여러 번) 호출되지만 모든 파일에 대해 호출되는 것은 아닙니다.
나는 제거 basename
아마 잘못 때문에 당신의이 질문 : 당신은 이동 것 foo/bar/file8
까지 file8_renamed
하지 foo/bar/file8_renamed
.
편집 (의견에서 제안한대로) :
find
없이 단축 추가xargs
- 보안 스티커 추가
답변
첫 번째 답변을 시도 하고 조금 놀아 본 후에 나는 -execdir
다음을 사용하여 약간 짧고 덜 복잡하게 할 수 있음을 발견했습니다 .
find . -type f -name 'file*' -execdir mv {} {}_renamed ';'
필요한 것을 정확하게 수행 해야하는 것처럼 보입니다.
답변
또 다른 방법은 while read
루프 오버 find
출력 을 사용하는 것 입니다. 이를 통해 각 파일 이름에 변수로 액세스 sh -c
하여 find
의 -exec
옵션을 사용하여 별도의 프로세스를 생성하는 추가 비용 / 잠재적 인 보안 문제에 대해 걱정할 필요가 없습니다 .
find . -type f -name 'file*' |
while IFS= read file_name; do
mv "$file_name" "${file_name##*\/}_renamed"
done
그리고 사용중인 쉘이 구분 기호 -d
를 지정하는 옵션을 read
지원하는 경우 다음을 사용하여 이상한 이름의 파일 (예 : 줄 바꿈)을 지원할 수 있습니다.
find . -type f -name 'file*' -print0 |
while IFS= read -d '' file_name; do
mv "$file_name" "${file_name##*\/}_renamed"
done
답변
첫 번째 답변 을 확장 하고 ./
경로 접두사가 파일 이름 인수에 있기 때문에 파일 이름에 추가 할 수는 없습니다 .
Thomas Erker의 답변을 수정하면 더 일반적인 접근 방식입니다.
find . -name PATTERN -printf "%f\0" | xargs --null -I{} mv {} "prefix {} suffix"
xargs 옵션 :
--null
전달 된 각 인수 stdin
가 널 문자 ( \0
)로 끝나는 것을 나타냅니다 . 이런 식으로 파일 이름에 공백이 포함될 수 있습니다. 그렇지 않으면 각 단어가 mv
명령 의 다른 매개 변수로 위협됩니다 .
-I replace-str
모든 발생은 replace-str
에서 읽은 인수로 대체됩니다 stdin
. 따라서 필요한 경우 다른 문자열로 변경할 수 있습니다.
답변
난과 비슷한 할 수 있었다 for
, find
등을 mv
.
for i in $(find . -name 'config.yml'); do mv $i $i.bak; done
모든 config.yml
파일을 찾아서 이름을 바꿉니다.config.yml.bak