확장자를 변경하지 않고 모든 파일의 이름을 재귀적으로 바꾸시겠습니까?

확장자를 변경하지 않고 모든 파일의 이름을 재귀적으로 바꾸시겠습니까?

확장자를 변경하지 않고 여러 수준의 하위 디렉터리에 있는 모든 파일의 이름을 재귀적으로 바꾸는 방법은 무엇입니까?

다음은 (공간을 절약하기 위해) 내가 가지고 있는 것의 단순화된 버전입니다. 논의를 위해 모든 파일의 제목은 동일하지만 원래 확장자는 유지하고 싶습니다. 디렉터리당 하나 이상의 파일이 존재하지 않으므로 복제가 불가능합니다.

단순화를 위해 이들을 모두 호출하고 foo그 뒤에 현재 확장명을 붙입니다.

따라서 명확히 하면 ,
Asset\ 1.pdf, Asset\ 1.png,는 , , 등이 됩니다.Asset\ [email protected]Asset\ 1.svg

foo.pdffoo.pngfoo.pngfoo.svg


나는 보통 for다음과 같이 매개변수 확장과 반복을 사용합니다.

for f in */*; do mv "$f" "${f%/*}/foo.${f##*.}"; done  

그러나 재귀적이지는 않습니다. 그래서 나는 find.. -exec또는 이와 유사한 것을 사용하는 것을 선호합니다 .


~/Desktop/Project/Graphics/
├── Huge
│   ├── PDF
│   │   └── Asset\ 1.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── Asset\ 1.png
│   │   └── 4x
│   │       └── Asset\ [email protected]
│   └── SVG
│       └── Asset\ 1.svg
├── Large
│   ├── PDF
│   │   └── ProjectAsset\ 2.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── ProjectAsset\ 2.png
│   │   └── 4x
│   │       └── ProjectAsset\ [email protected]
│   └── SVG
│       └── ProjectAsset\ 2.svg
├── Medium
│   ├── PDF
│   │   └── ProjectAsset\ 3.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── ProjectAsset\ 3.png
│   │   └── 4x
│   │       └── ProjectAsset\ [email protected]
│   └── SVG
│       └── ProjectAsset\ 3.svg
├── Small
│   ├── PDF
│   │   └── ProjectAsset\ 4.pdf
│   ├── PNG
│   │   ├── 1x
│   │   │   └── ProjectAsset\ 4.png
│   │   └── 4x
│   │       └── ProjectAsset\ [email protected]
│   └── SVG
│       └── ProjectAsset\ 4.svg
└── Tiny
    ├── PDF
    │   └── Asset\ 5.pdf
    ├── PNG
    │   ├── 1x
    │   │   └── Asset\ 5.png
    │   └── 4x
    │       └── Asset\ [email protected]
    └── SVG
        └── Asset\ 5.svg

30 directories, 20 files

답변1

이는 다음과 매우 유사합니다 find...-exec. 인수 확장을 사용할 수 있도록 셸을 호출하고, 새 파일 이름을 구성할 수 PARENT있도록 디렉터리를 추출한 EXTENSION다음 PARENT/NAME.EXTENSION이동/이름 바꾸기를 수행합니다.

find target_dir -name '?*.*' -type f -exec sh -c '
  ret=0
  for file do
    head=${file%/*}
    mv -- "$file" "$head/NAME.${file##*.}" || ret=$?
  done
  exit "$ret"' sh {} +

위의 내용을 Dry Run 하려면 echo앞에 삽입하세요.mv

숨겨진 파일도 처리합니다.


액세스 권한이 있으면 다음을 zsh실행할 수 있습니다.

autoload zmv
zmv -n '(**/)(*.*)' '${1}NAME.${2:e}'

-n결과가 만족스러우면 삭제하세요.

(#qD)숨겨진 파일은 기본적으로 건너뛰지만, 이를 처리하려면 glob 한정자를 사용할 수 있습니다.

autoload zmv
zmv -n '(**/)(?*.*)(#qD)' '${1}NAME.${2:e}'

답변2

Bash를 사용하는 경우 모든 디렉터리를 반복하는 것이 좋습니다.

$ shopt -s globstar
$ for f in ./Desktop/**/*; do [[ -f $f ]] && 
           mv -n "$f" "${f%/*}/foo.${f##*.}"; done

기존 파일(있는 경우)을 덮어쓰지 않도록 -n추가 되었습니다 .mv

이 작업은 find(in)를 통해서도 수행할 수 있습니다.하나쉘 호출(파일당 하나의 쉘을 호출하는 것보다 빠름):

$ find ./Desktop -type f -exec sh -c '
       for f; do echo mv -n "$f" "${f%/*}/foo.${f##*.}"; done' findsh {} \+

echo이 명령이 요구 사항을 충족하는 경우 제거하십시오.

답변3

지나치게 단순화한 것일 수도 있지만 디렉터리 계층 구조의 최대 깊이(여기서는 3)를 알고 있다면 어떨까요?

for f in */* */*/* */*/*/*; do ... ; done 

오류 검사를 추가하시겠습니까?

답변4

find ~/Desktop/Project/Graphics/ -type f -exec sh -c 'f={}; mv $f ${f%/*}/foo.${f##*.}' \;

sh기본 쉘 호출을 나타냅니다. bash, zsh 등으로 변경할 수 있습니다.

관련 정보