find를 사용하여 여러 파일의 이름을 바꾸는 방법

find를 사용하여 여러 파일의 이름을 바꾸는 방법

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

파일 이름이 쉘 변수로 해석되지 않기 때문에 작동하지 않습니다.

답변1

귀하의 접근 방식에 대한 간단한 수정 사항은 다음과 같습니다.

find . -type f -name 'file*' -exec sh -c 'x="{}"; mv "$x" "${x}_renamed"' \;

그러나 일치하는 파일이 많은 경우 일치하는 mv항목마다 새 셸을 시작(a 실행)하므로 비용이 매우 많이 듭니다. 파일 이름에 재미있는 문자가 포함되어 있으면 폭발합니다. 보다 효율적이고 안전한 방법은 다음과 같습니다.

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
  • 안전 스티커가 추가되었습니다.

답변2

시도한 후첫 번째 답변조금 놀아 본 후 다음 명령을 사용하여 약간 단축하고 단순화할 수 있음을 발견했습니다 -execdir.

find . -type f -name 'file*' -execdir mv {} {}_renamed ';'

그것은 당신이 필요로하는 것을 정확하게 수행해야 할 것 같습니다.

답변3

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

답변4

, 및 를 사용하여 for비슷한 find작업을 수행할 수 있었습니다 mv.

for i in $(find . -name 'config.yml'); do mv $i $i.bak; done

config.yml그러면 모든 파일을 찾아 이름을 다음으로 바꿉니다.config.yml.bak

관련 정보