이 명령을 사용하여 파일 이름을 재귀적으로 바꿉니다.
find -iname \*.bak | rename 's/.bak/.old/'
하지만 현재 디렉터리를 제외하고 싶습니다. 예:
.bak
dir1/.bak
dir2/.bak
...
나는 이것을 원한다:
.bak
dir1/.old
dir2/.old
...
답변1
find
조건자 지원 과 함께 a를 사용하세요 -mindepth
.
find . -mindepth 2 -type f -name '*.bak' | rename 's/\.bak$/.old/'
조건자를 사용하면 -mindepth
일치 항목이 발생할 수 있는 최소 검색 깊이를 정의할 수 있습니다. 깊이 0은 루트 검색 경로 자체( .
)이고, 깊이 1은 루트 검색 경로 바로 아래에 있는 항목(예: ./somename
)이고, 깊이 2는 루트 검색 경로 바로 아래에 있는 항목(예 ./somename/other
: )입니다.
-iname
rename
어쨌든 다른 유형의 파일 이름 접미사 대문자로 파일 이름을 바꾸지 않으므로 대소문자 구분 일치가 필요하지 않으므로 이를 test 로 변경했습니다 -name
. 또한 이름에 문자열이 포함된 파일(예: )이 이상한 방식으로 이름이 바뀌지 않도록(예: 로 이름 변경 ) 귀하의 rename
호출을 수정했습니다 .bak
rebak.bak
r.old.bak
-type f
또한 일반 파일 만 find
고려된다는 점, 즉 디렉토리 등은 고려되지 않는다고 덧붙였습니다 .
보다 이식성이 뛰어난 솔루션의 경우:
find . -mindepth 2 -type f -name '*.bak' -exec sh -c '
for pathname do
mv "$pathname" "${pathname%.bak}.old"
done' sh {} +
이는 유틸리티에 의존하지 않습니다 rename
.
find . -mindepth 2 -type f -name '*.bak' -exec rename 's/\.bak$/.old/' {} +
이것은 rename
통화에서 직접 나온 것입니다 find
.
관련된:
를 사용하면 완전히 건너뛰고 다음을 수행 bash
할 수 있습니다.find
shopt -s globstar dotglob
rename 's/\.bak$/.old/' ./*/**/*.bak
와일드카드 패턴은 **
임의 개수의 중간 하위 디렉터리와 일치합니다. 이 특수 모드는 globstar
쉘 옵션을 통해 활성화됩니다. 초기는 ./*/
현재 디렉터리 자체가 아닌 현재 디렉터리의 하위 디렉터리만 찾도록 보장합니다.
쉘 dotglob
옵션을 사용하면 숨겨진 이름을 패턴과 일치시킬 수 있습니다.
그러나 위 명령은 일반 파일을 구체적으로 선택하지 않습니다(그러나 사용자 명령 find
도 마찬가지입니다 ). 이렇게 하려면 루프를 사용하세요.
shopt -s globstar dotglob
for pathname in ./*/**/*.bak; do
[[ ! -f $pathname ]] && continue
rename 's/\.bak$/.old/' "$pathname"
done
또한 심볼릭 링크의 이름이 일반 파일로 변경됩니다.
답변2
이 시도
find -iname \*.bak -not -path "./.bak" | rename 's/.bak/.old/'