중복된 파일 이름으로 복잡한 폴더 구조를 평면화

중복된 파일 이름으로 복잡한 폴더 구조를 평면화

폴더 구조가 복잡한 폴더가 있습니다.

├── folder1
│   ├── 0001.jpg
│   └── 0002.jpg
├── folder2
│   ├── 0001.jpg
│   └── 0002.jpg
├── folder3
│    └── folder4
│         ├── 0001.jpg
│         └── 0002.jpg
└── folder5
     └── folder6
           └── folder7
                ├── 0001.jpg
                └── 0002.jpg   

모든 파일이 폴더1_0001.jpg, 폴더1_0002.jpg...folder5_folder6_folder7_0001.jpg 등과 같은 고유한 이름을 가진 상위 디렉터리에 있도록 폴더 구조를 평면화하고 싶습니다.

에서 제안한 코드를 사용해 보았습니다."플랫 폴더 구조"

$ find */ -type f -exec bash -c 'file=${1#./}; echo mv "$file" "${file//\//_}"' _ '{}' \;

echo작동 중임을 보여줍니다 .

mv folder3/folder4/000098.jpg folder3_folder4_000098.jpg

그러나 출력 파일은 상위 디렉터리에 저장되지 않습니다. 전체 드라이브를 검색했지만 출력 파일을 찾을 수 없습니다.

나도 시도했다"Bash의 파일 이름으로 플랫 폴더 구조"

$ find . -type f -name "*.jpg" | sed 'h;y/\//_/;H;g;s/\n/ /g;s/^/cp -v /' | sh

-v작동 중임을 보여줍니다.

‘./folder3/folder4/000098.jpg’ -> ‘._folder3_folder4_000098.jpg’

그러나 출력 결과 상위 디렉터리에 숨겨진 파일이 생성되어 작업 흐름이 복잡해졌습니다. 다음을 사용하여 상위 디렉토리에서 이러한 숨겨진 파일을 볼 수 있습니다.ls -a

나는 또한 아래에 제안된 코드를 시도했다"중복 파일의 이름을 바꾸려면 Flatten Folders 명령을 사용하십시오."

find . -mindepth 2 -type f | xargs mv --backup=numbered -t . && find . -type d -empty -delete

하지만 이 명령은 비슷한 파일 이름을 가진 파일을 덮어씁니다.

비슷한 이름의 파일을 덮어쓰지 않고 복잡한 폴더 구조를 평면화하는 방법에 대한 제안 사항이 있습니까? 현재 솔루션은 한 수준 깊이의 폴더 구조에서만 작동하는 것 같습니다.

나의 궁극적인 목표는 다음에 설명된 대로 고유 이름을 연속 숫자로 변환하는 것입니다."폴더의 파일 이름을 연속된 번호로 변경"

 a=1
  for i in *.jpg; do
  new=$(printf "%04d.jpg" "$a") #04 pad to length of 4
  mv -- "$i" "$new"
  let a=a+1
 done

답변1

귀하의 질문에 대한 첫 번째 해결책이 왜 작동하지 않는지 모르겠습니다. 나는 당신이 그것을 삭제하는 것을 잊었다고 가정할 수 있습니다 echo. 여전히 실행 중이라고 가정하면 필요한 작업을 수행해야 하는 또 다른 방법이 있습니다 bash.

shopt -s globstar
for i in **/*jpg; do mv "$i" "${i//\//_}"; done

설명하다

  • 원하는 수의 디렉터리나 파일을 반복적으로 일치시키는 shopt -s globstarbash의 globstar기능을 켭니다 .**
  • for i in **/*jpg;이름이 로 끝나는 모든 파일(또는 디렉터리)을 반복하고 .jpg각 파일을 $i.
  • "${i//\//_}"/의 모든 인스턴스가 포함된 현재 파일(또는 디렉터리)의 이름입니다 _.

이름이 끝나는 디렉터리가 있고 .jpg이를 건너뛰려면 대신 다음을 수행하세요.

shopt -s globstar
for i in **/*jpg; do [ -f "$i" ] && echo mv "$i" "${i//\//_}"; done

확장자에 관계없이 모든 파일에 대해:

shopt -s globstar
for i in **/*; do [ -f "$i" ] && echo mv "$i" "${i//\//_}"; done

답변2

renamePerl (때때로 Perl이라고도 함 ) 이 있는 경우 prename다음을 수행할 수 있습니다.

find folder* -type f -name '*.jpg' -exec rename 's!/!_!g' {} \;

이는 각 파일 이름 경로를 취하고 모든 항목 /_.

파일 이름을 일련의 연속된 4자리 파일 이름으로 바꾸려면 원본 데이터 세트에서 해당 이름을 사용할 수 있습니다. 디렉터리 및 파일 이름에 일반 영숫자가 포함된 경우에만 작동합니다. 특히 공백, 쉘 구두점 또는 기타 공백이 있으면 실패합니다.

rename 's!.*!sprintf "%04d.jpg", ++$a!e' $(find folder* -type f -name '*.jpg' | sort)

rename -n ...무엇이든 변경할 때 어떤 일이 발생하는지 확인하거나 rename -v ...실행 시 어떤 일이 발생하는지 확인 하려면 이를 사용하세요 .

답변3

pax -rws'|/|_|g' folder*/ .

...파일 이름이 겹칠 수 없는 한 작동합니다. 이를 보다 안전하게 수행하려면 -l링크 옵션을 사용하고 트리를 다른 경로에 미러링한 다음 이전 트리를 삭제하기 전에 새 트리를 확인하십시오.

답변4

다음 스크립트를 사용하여 성공했습니다.

#!/bin/sh

for folder in $(ls $1)
do
  for file in $(ls ${folder})
  do
    mv ${folder}/${file} $1/${folder}_${file}
  done
  rmdir ${folder}
done

관련 정보