찾기를 사용하여 여러 파일의 이름을 바꾸는 방법 filen_renamed)의 이름을 바꾸고

명령 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


답변