파일 이름 앞에 폴더 이름을 추가하여 파일을 한 단계 위로 이동하시겠습니까?

파일 이름 앞에 폴더 이름을 추가하여 파일을 한 단계 위로 이동하시겠습니까?

테스트 환경:

  • 0to 부터 디렉토리를 만들고 to 9부터 파일로 채웁니다 .az
    $ mkdir {0..9} && touch {0..9}/{a..z}
    
  • 에 의한 결과 find:
    $ find -type f
    ./0/a
    ./0/b
    
    ...
    
    ./9/y
    ./9/z
    

출력을 다음과 같이 변환하려면 어떻게 해야 합니까?

./0a    
./0b

...

./9y
./9z

답변1

Perl의 독립 rename실행형 명령을 사용하면:

rename -n 's|/||' */*

모든 것이 괜찮아 보이면 -n나머지 빈 디렉터리를 제거한 다음 제거합니다.

rmdir {0..9}

답변2

POSIX 도구를 사용하면

find . -type f -exec sh -c 'for f; do dirn="${f%/*}"; mv -- "$f" "$dirn${f##*/}"; done' sh {} +

find쉘을 호출하고 각 파일에 대해 for 루프를 실행합니다.

  • dirn="${f%/*}"파일 이름에서 마지막 슬래시 뒤의 모든 항목을 제외하고 포함하여 상위 디렉터리 이름을 가져옵니다.

  • ${f##*/}파일 이름의 마지막 슬래시 앞의 모든 항목을 제외하고 포함하여 경로 없이 파일 이름을 가져옵니다.

이 두 쉘 구성은 다음과 동일합니다.dirname그리고basename, 따라서 명령의 동등한 형식은 다음과 같습니다.

find . -type f -exec sh -c 'for f; do mv -- "$f" "$(dirname "$f")$(basename "$f")"; done' sh {} +

, 각 파일에 대해 두 개의 추가 프로세스를 생성해야 하므로 속도가 느려집니다.

예제에서 볼 수 있듯이 단일 디렉터리 이상으로 내려갈 필요가 없으면 간단한 셸 루프를 사용하면 됩니다.

for f in */*; do dirn="${f%/*}"; echo mv -- "$f" "$dirn${f##*/}"; done

관련 정보