답변:
이식 가능한 방법 (POSIX 호환 시스템에서 작동) :
find /the/path -depth -name "*.abc" -exec sh -c 'mv "$1" "${1%.abc}.edefg"' _ {} \;
bash4에서 globstar를 사용하여 재귀 글로브를 얻을 수 있습니다 (**).
shopt -s globstar
for file in /the/path/**/*.abc; do
mv "$file" "${file%.abc}.edefg"
done
rename
Ubuntu 의 (perl) 명령은 perl 정규식 구문을 사용하여 파일 이름을 바꿀 수 있으며, globstar 또는 find
:
# Using globstar
shopt -s globstar
files=(/the/path/**/*.abc)
# Best to process the files in chunks to avoid exceeding the maximum argument
# length. 100 at a time is probably good enough.
# See http://mywiki.wooledge.org/BashFAQ/095
for ((i = 0; i < ${#files[@]}; i += 100)); do
rename 's/\.abc$/.edefg/' "${files[@]:i:100}"
done
# Using find:
find /the/path -depth -name "*.abc" -exec rename 's/\.abc$/.edefg/' {} +
${1%.abc}...
sh -c
첫 번째 인수는 $ 0에 할당되고 나머지 인수는 위치 매개 변수에 할당되므로 필요합니다 . 따라서는 _
더미 인수이고 '{}'은의 첫 번째 위치 인수 sh -c
입니다.
모든 파일이 같은 폴더에 있으면 필요한 작업을 수행합니다.
rename 's/.abc$/.edefg/' *.abc
파일의 이름을 재귀 적으로 바꾸려면 다음을 사용하십시오.
find /path/to/root/folder -type f -name '*.abc' -print0 | xargs -0 rename 's/.abc$/.edefg/'
rename 's/.abc$/.edefg/' /path/to/root/folder/**/*.abc
Bash의 최신 버전에서.
s
처음에, 그리고 다른 어떤 옵션 것은 내가 거기에 사용할 수 있습니다. 감사 !
재귀 이름 바꾸기의 한 가지 문제는 파일을 찾는 데 사용하는 모든 방법이 rename
파일 이름뿐만 아니라 전체 경로를에 전달한다는 것 입니다. 따라서 중첩 된 폴더에서 복잡한 이름 바꾸기를 수행하기가 어렵습니다.
의 문제를 해결하기 위해 find
의 -execdir
조치를 사용 합니다. -execdir
대신에 사용 -exec
하면 지정된 명령이 일치하는 파일을 포함하는 서브 디렉토리에서 실행됩니다. 따라서 전체 경로를로 전달하는 대신 rename
로만 전달 ./filename
됩니다. 따라서 정규식을 훨씬 쉽게 작성할 수 있습니다.
find /the/path -type f \
-name '*.abc' \
-execdir rename 's/\.\/(.+)\.abc$/version1_$1.abc/' '{}' \;
상세히:
-type f
디렉토리가 아닌 파일 만 찾습니다.-name '*.abc'
.abc로 끝나는 파일 이름과 만 일치합니다.'{}'
-execdir
찾은 경로를 삽입 할 위치를 표시하는 자리 표시 자입니다 . 작은 따옴표는 공백과 셸 문자로 파일 이름을 처리 할 수 있도록해야합니다.-type
와 -name
bash는 줄 연속 문자입니다. 이 예제를 더 읽기 쉽게 만들기 위해 사용하지만 명령을 한 줄에 모두 넣는 경우에는 필요하지 않습니다.-execdir
줄 끝에 백 슬래시 가 필요합니다. 세미콜론을 이스케이프하면에 의해 실행되는 명령이 종료됩니다 -execdir
. 장난!정규식에 대한 설명 :
s/
정규식의 시작\.\/
-execdir이 전달하는 선행 ./와 일치합니다. \를 사용하여. 및 / 메타 문자 (참고 :이 부분은 버전에 따라 다릅니다 find
. @apollo 사용자의 의견 참조)(.+)
파일 이름과 일치하십시오. 괄호는 나중에 사용하기 위해 일치를 캡처합니다.\.abc
점을 탈출, abc와 일치$
문자열의 끝에 일치를 고정
/
정규식의 "일치"부분의 끝과 "대체"부분의 시작을 표시합니다.
version1_
이 텍스트를 모든 파일 이름에 추가
$1
괄호로 캡처 한 기존 파일 이름을 참조합니다. "일치"부분에 여러 괄호 세트를 사용하는 경우 여기에서 $ 2, $ 3 등을 사용하여 괄호를 참조 할 수 있습니다..abc
새 파일 이름은 .abc로 끝납니다. "바꾸기"섹션에서 도트 메타 문자를 이스케이프 할 필요가 없습니다./
정규식의 끝전에
tree --charset=ascii
|-- a_file.abc
|-- Another.abc
|-- Not_this.def
`-- dir1
`-- nested_file.abc
후
tree --charset=ascii
|-- version1_a_file.abc
|-- version1_Another.abc
|-- Not_this.def
`-- dir1
`-- version1_nested_file.abc
힌트 : rename
의 -n 옵션이 유용합니다. 드라이 런을 수행하고 변경 될 이름을 표시하지만 변경하지는 않습니다.
--execdir
선행을 통과하지 못했기 ./
때문에 \.\/
정규 표현식 의 일부를 생략 할 수 있습니다. 내가 OSX하지 우분투이기 때문에 월 즉
또 다른 휴대용 방법 :
find /the/path -depth -type f -name "*.abc" -exec sh -c 'mv -- "$1" "$(dirname "$1")/$(basename "$1" .abc).edefg"' _ '{}' \;
# Rename all *.txt to *.text
for f in *.txt; do
mv -- "$f" "${f%.txt}.text"
done
구문 분석하지 않아야하는 이유에 대한 항목도 참조하십시오 ls
.
편집 : basename을 사용해야하는 경우 구문은 다음과 같습니다.
for f in *.txt; do
mv -- "$f" "$(basename "$f" .txt).text"
done
https://unix.stackexchange.com/questions/19654/changing-extension-to-multiple-files
이것이 내가하고 원하는 방식으로 일한 것입니다. 나는 mv
명령을 사용했다 . .3gp
파일 이 여러 개 있는데 모두 파일 이름을 바꾸고 싶었습니다..mp4
여기에 짧은 oneliner가 있습니다.
for i in *.3gp; do mv -- "$i" "ren-$i.mp4"; done
단순히 현재 디렉토리를 스캔하고 모든 .3gp 파일을 가져온 다음 mv를 사용하여 이름을 바꿉니다. ren-name_of_file.mp4
file.3gp
에 file.3gp.mp4
대부분의 사람들이 원하는 것을하지 않을 수있는.
.3gp
또는 .mp4
여기에는 설명을 위해 단지 있었다.
basename "$i" .mp4
"ren- $ i.mp4"대신 이전 확장을 제거하는 데 사용 합니다.
파일 및 디렉토리 이름 변경 find -execdir | rename
단순히 접미사가 아닌 파일과 디렉토리의 이름을 바꾸려면 좋은 패턴입니다.
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
find . -depth -execdir rename 's/findme/replaceme/' '{}' \;
awesome -execdir
옵션 은와 달리 명령을 cd
실행하기 전에 디렉토리를 수행합니다 .rename
-exec
-depth
부모 디렉토리가 누락 될 때 발생할 수있는 잠재적 인 문제를 방지하기 위해 이름 변경은 먼저 자식에서, 그런 다음 부모에서 일어나야합니다.
-execdir
이름이 아닌 이름이 아닌 입력 경로에서 이름이 제대로 재생되지 않기 때문에 필수입니다 (예 : 다음 실패).
rename 's/findme/replaceme/g' acc/acc
PATH
때문에 해킹이 필요 -execdir
하나 매우 짜증나는 단점이 find
매우 독단적를하고 아무것도 할 거부 -execdir
당신이 당신의 상대 경로가있는 경우 PATH
예를 들어 환경 변수 ./node_modules/.bin
와 실패를 :
find : 상대 경로 './node_modules/.bin'이 PATH 환경 변수에 포함되어 있으며 find의 -execdir 조치와 함께 사용하면 안전하지 않습니다. $ PATH에서 해당 항목을 제거하십시오
PATH에있는 디렉토리에 대해 '-execdir'조치를 사용하는 것이 안전하지 않은 이유 는 무엇입니까?
-execdir
POSIX에 대한 GNU 찾기 확장 입니다. rename
Perl 기반이며 rename
패키지 에서 제공 됩니다. 우분투에서 테스트 18.10.
미리보기 대안 이름 바꾸기
입력 경로가 출신이 아니 find
거나 상대 경로 성가심이 충분하면 Perl lookahead를 사용하여 다음과 같이 디렉토리 이름을 안전하게 바꿀 수 있습니다.
git ls-files | sort -r | xargs rename 's/findme(?!.*\/)\/?$/replaceme/g' '{}'
나는을 위해 편리한 아날로그를 발견하지 않았습니다 -execdir
와 xargs
: https://superuser.com/questions/893890/xargs-change-working-directory-to-file-path-before-executing/915686
는 sort -r
더 이상 경로가 동일한 접두사와 짧은 사람 한 후 온 이후 파일이 각 디렉토리 이후에 올 수 있도록해야합니다.