이름 바꾸기를 사용하여 파일 이름(디렉토리 제외)의 유효하지 않은 문자를 반복적으로 바꾸는 스크립트

이름 바꾸기를 사용하여 파일 이름(디렉토리 제외)의 유효하지 않은 문자를 반복적으로 바꾸는 스크립트

[^A-Za-z0-9._-]저는 특정 파일 형식(이 경우)을 제외한 모든 문자를 찾아서 밑줄로 바꾸는 스크립트를 작성하고 있습니다 . 현재 경로에서 재귀적으로 실행되기를 원합니다. 저는 우분투를 사용하고 있습니다..avi_

폴더 이름을 만들 때 폴더 이름을 제어할 수 있으므로 폴더 이름을 변경하고 싶지도 변경할 필요도 없습니다. 다음 링크를 참조하여 현재 제가 가지고 있는 내용은 다음과 같습니다.

SE 참조

find . -depth -exec rename 's!([^/]*\Z)/[^A-Za-z0-9._-]/_/g' *.avi {} +

나는 분명히 뭔가를 놓치고 있습니다. 도와주세요. :)

답변1

코드가 작동하지 않는 이유

와일드카드 패턴은 *.avi이전에 실행된 셸에 의해 확장되므로 그 효과는 현재 디렉터리에 파일이 있는지 여부에 따라 달라집니다. 바라보다findfind*.avi파일이 맨 위에 있을 때 찾기가 반복되지 않습니다.더 많은 설명을 원하시면. 하위 디렉토리에서 확장하려면 *.avi세 가지 다른 작업을 수행해야 합니다. 원래 쉘이 확장되지 않도록 패턴을 인용하고, 와일드카드 확장을 수행하기 위해 각 하위 디렉토리에서 추가 쉘을 실행하도록 조정하고, find파일 유형 대신 명령을 사용합니다. 검색 디렉토리.

또한 코드 는 rename결국 {} +.rename

또한 Perl 코드에 구문 오류가 있습니다.

zsh를 사용한 작업 솔루션

autoload -Uz zmv # best in ~/.zshrc

zmv -n '(**/)(*.avi)(#qD^/)' '$1${2//[^a-zA-Z0-9._-]/_}'

^/예 제외를 선택하세요목차. 다음 .으로 교체정기적인파일만. -n이다시운전. 만족스러우면 삭제하세요.

실제 솔루션 findrename

Perl 기반 변형 renamefind지원되는 구현 사용 -execdir:

LC_ALL=C find . -depth -name '*[!a-zA-Z0-9._-]*.avi' ! -type d -execdir \
  rename 's/[^a-zA-Z0-9._-]/_/g' {} +

하지만 이 접근 방식에는 몇 가지 주의 사항이 있습니다.

  • 달리다적어도rename이름을 바꿀 파일이 포함된 디렉터리당 하나의 인스턴스가 있습니다( rename파일당 하나, 일부 find구현/버전 에서는 -execdir ... {} +실제로 .( -execdir ... {} \;파일당 zmv하나씩 실행 mv하지만 mv내장 명령을 사용하여 zmodload zsh/files속도를 높일 수 있음)). .
  • 사용 -execdir, find실행 명령디렉토리에이러한 파일을 포함하고 디렉터리에 대한 상대 경로를 명령에 전달합니다. 일부 find구현(GNU 구현)은 ./파일에 접두사를 추가하지만 일부는 그렇지 않습니다. do renameaccept 옵션 의 일부 변형뒤쪽에즉, 이름이 .perl로 시작하는 파일이 있는 경우 -문제가 발생할 수 있습니다 .
  • 파일 이름에 일련의 바이트가 포함되어 있더라도 그렇지 않으면 로케일에서 유효한 문자를 형성하기 위해 LC_ALL=Cfor 를 사용해야 합니다 . 이는 상속되었으며 대부분의 변형에서는 ASCII에서만 작동합니다. 그러나 이는 멀티바이트 문자를 해당 문자와 ​​동일한 바이트 수로 대체한다는 의미입니다. 예를 들어 UTF-8은 멀티바이트 문자와 문자로 디코딩할 수 없는 모든 바이트를 각각 하나의 문자로 변환하므로 이름을 로 바꾸는 것이 좋습니다 .-namerename_stéphanest__phanest_phanezsh_
  • 와 달리 zsh이름 바꾸기를 시작하기 전에 zmv온전한 검사를 수행하지 않습니다 (예: 두 파일은 a+b.avi및 처럼 동일한 이름으로 끝나지 않습니다). 하지만 기존 파일을 덮어쓰면 안 됩니다.[email protected]rename

답변2

우리가 말하면

rename 's/[^A-Za-z0-9.-]/_/g' -- *.avi

현재 디렉토리에서 파일 이름 접미사가 있는 모든 파일의 이름을 올바르게 바꾸며 .avi현재 디렉토리(현재 디렉토리 포함) 아래의 모든 디렉토리에 적용할 수 있습니다.

find . -type d -exec sh -c '
    for dirpath do
        ( cd "$dirpath" && rename "s/[^A-Za-z0-9.-]/_/g" -- *.avi )
    done' sh {} +

발견된 디렉토리 배치의 경우, 발견된 디렉토리로 변경하고 명령을 실행하는 짧은 인라인 스크립트를 실행합니다 rename.

관련 정보