재귀적 이름 바꾸기는 현재 디렉터리를 제외합니다.

재귀적 이름 바꾸기는 현재 디렉터리를 제외합니다.

이 명령을 사용하여 파일 이름을 재귀적으로 바꿉니다.

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: )입니다.

-inamerename어쨌든 다른 유형의 파일 이름 접미사 대문자로 파일 이름을 바꾸지 않으므로 대소문자 구분 일치가 필요하지 않으므로 이를 test 로 변경했습니다 -name. 또한 이름에 문자열이 포함된 파일(예: )이 이상한 방식으로 이름이 바뀌지 않도록(예: 로 이름 변경 ) 귀하의 rename호출을 수정했습니다 .bakrebak.bakr.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/'

관련 정보