[^A-Za-z0-9._-]
저는 특정 파일 형식(이 경우)을 제외한 모든 문자를 찾아서 밑줄로 바꾸는 스크립트를 작성하고 있습니다 . 현재 경로에서 재귀적으로 실행되기를 원합니다. 저는 우분투를 사용하고 있습니다..avi
_
폴더 이름을 만들 때 폴더 이름을 제어할 수 있으므로 폴더 이름을 변경하고 싶지도 변경할 필요도 없습니다. 다음 링크를 참조하여 현재 제가 가지고 있는 내용은 다음과 같습니다.
find . -depth -exec rename 's!([^/]*\Z)/[^A-Za-z0-9._-]/_/g' *.avi {} +
나는 분명히 뭔가를 놓치고 있습니다. 도와주세요. :)
답변1
코드가 작동하지 않는 이유
와일드카드 패턴은 *.avi
이전에 실행된 셸에 의해 확장되므로 그 효과는 현재 디렉터리에 파일이 있는지 여부에 따라 달라집니다. 바라보다find
find
*.avi
파일이 맨 위에 있을 때 찾기가 반복되지 않습니다.더 많은 설명을 원하시면. 하위 디렉토리에서 확장하려면 *.avi
세 가지 다른 작업을 수행해야 합니다. 원래 쉘이 확장되지 않도록 패턴을 인용하고, 와일드카드 확장을 수행하기 위해 각 하위 디렉토리에서 추가 쉘을 실행하도록 조정하고, find
파일 유형 대신 명령을 사용합니다. 검색 디렉토리.
또한 코드 는 rename
결국 {} +
.rename
또한 Perl 코드에 구문 오류가 있습니다.
zsh를 사용한 작업 솔루션
autoload -Uz zmv # best in ~/.zshrc
zmv -n '(**/)(*.avi)(#qD^/)' '$1${2//[^a-zA-Z0-9._-]/_}'
^/
예 제외를 선택하세요목차. 다음 .
으로 교체정기적인파일만. -n
이다시운전. 만족스러우면 삭제하세요.
실제 솔루션 find
과rename
Perl 기반 변형 rename
및 find
지원되는 구현 사용 -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 구현)은./
파일에 접두사를 추가하지만 일부는 그렇지 않습니다. dorename
accept 옵션 의 일부 변형뒤쪽에즉, 이름이 .perl로 시작하는 파일이 있는 경우-
문제가 발생할 수 있습니다 . - 파일 이름에 일련의 바이트가 포함되어 있더라도 그렇지 않으면 로케일에서 유효한 문자를 형성하기 위해
LC_ALL=C
for 를 사용해야 합니다 . 이는 상속되었으며 대부분의 변형에서는 ASCII에서만 작동합니다. 그러나 이는 멀티바이트 문자를 해당 문자와 동일한 바이트 수로 대체한다는 의미입니다. 예를 들어 UTF-8은 멀티바이트 문자와 문자로 디코딩할 수 없는 모든 바이트를 각각 하나의 문자로 변환하므로 이름을 로 바꾸는 것이 좋습니다 .-name
rename
_
stéphane
st__phane
st_phane
zsh
_
- 와 달리
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
.