2017-02-11 2 views
0

하여 파일 이름 바꾸기, 나는 폴더 계층 구조를 평평하게하려고 노력하지만, 파일이 내부에 동일한 이름대로, 나는 과거의 폴더 이름과 파일 이름을 확장하려는 :OSX 터미널 : OSX 터미널에서 계층 구조

내가 좋겠 여기에서 얻을 싶어 : 나는 운이 아직 (https://unix.stackexchange.com/questions/52814) 병합으로 이름을 변경 (Batch renaming files in OSX terminal)를 결합하는 시도했지만 한

/dirA1/dirB1/file1.ext 
/dirA1/dirB2/file1.ext 
... 
/dirA2/dirB1/file1.ext 
... 

/file1-dirA1-dirB1.ext 
/file1-dirA1-dirB2.ext 
... 
/file1-dirA2-dirB1.ext 
... 

에 ...

"찾기"로 시작하겠습니까? 하지만 "mv"에 디렉토리 이름을 어떻게 전달할 수 있습니까?

미리 감사드립니다.

답변

0

매우 빠르고, 안전,하지만 방법이처럼 교체를 수행하는 쉘 명령에 각 파일을 전달 -execfind을 사용하는 것입니다 :

(cd /path; find . -type f -exec sh -c 'newname=${1:2}; filename=${newname##*/}; dirname=${newname%/*}; newname=$filename-${dirname//\//-}; echo mv "$1" "$newname"' -- {} \;) 

cd /path 대신의 이유 find /path은 해당 기본 디렉토리의 상대 경로로 작업 할 수 있기 때문에 병합 된 파일 이름을 더 쉽게 만들 수 있습니다.

  • -exec sh -c '...' -- {}-c '...'는 지정된 명령을 실행하고, 실행 sh :

    는이 요소의 자세한 설명은 비트. {} 경로는 find입니다. -- ... 구문은 매개 변수를 위치 인수로 스크립트에 전달하며 $1, $2 등으로 액세스 할 수 있습니다.

  • newname=${1:2}은 첫 번째 위치 인수 인 $1을 가져와 첫 번째 두 문자를 건너 뛰고 하위 문자열을 추출합니다. find .의 출력에 ./으로 시작하는 경로가 있고 /-으로 바꾸기 전에 제거하려고하므로이 작업을 수행합니다.
  • filename=${newname##*/}
  • , 그것은
  • ${dirname//\//-} 모든 대체 후 마지막 / 모든 것을 제거하여 마지막 /
  • dirname=${newname%/*} 때까지 경로의 디렉토리 이름 부분 처음부터 모든 것을 추출물 제거하여, 경로의 파일 이름 부분을 추출 발생은 /이고 -입니다. 대신 교체의 /을 제거 할 경우이 파일 이름에 특수 문자가 작동하기 때문에, 당신은,이 기술은 안전 ${dirname//\//}

쓸 수 있습니다. 각 파일에 대해 sh을 실행하기 때문에 속도가 느립니다.

원본 파일의 빈 디렉토리가 남아이 단계 후

, 당신은 아마도 그들을 제거 할 :

find /path -type d -empty -delete 
+0

고마워요! 빨리 해봐. - newname = $ {1 : 2}와 newname // \/- 각각 정확히 무엇을 가르쳐 주시겠습니까? – Frank

+0

더 많은 설명을 추가하고 중요한 오타를 수정했습니다. 교체는'newname = $ {newname // \/-}'이어야하며, 편집 이전과 같이'newname = $ {newname // \/-} '이 아니어야합니다. – janos

+0

감사합니다, Janos! 사실, 원래의 파일 이름 뒤에/디렉토리 이름을 추가하고 싶습니다. mv에게 그것들을 붙이는 대신 인수를 덧붙이라고 어떻게? (또한/문자를 -로 바꾸지 않고/문자를 완전히 제거 할 수있는 방법은 무엇입니까?) "문자가없는"문자로 바꿀 수는 없습니까? – Frank

0
당신은 안전하게 while readfind … -print0 출력을 공급함으로써 모든 파일에 대해 sh을 실행하지 않고이 문제를 처리 할 수 ​​

루프처럼 :

while IFS= read -r -d '' old; do   # read filenames into $old 
              # -d '' : read until \0 
              # -r  : no backslash escapes 
              # IFS= : no trimming whitespace 
    if [[ $old =~ (.*)/(.*)\.(.*) ]]; then # regex with capture groups: 
     #   1 2  3 
     set -- "${BASH_REMATCH[@]}" 
     mv "$old" "${2}-${1//\/}.${3}" 
    fi 
done < <(find . -type f -print 0) 

set -- "${BASH_REMATCH[@]}"의 목적은 정규식 일치를 포함하는 배열의 구성원을 이동하는 단지입니다 그룹을 가독성을 위해 위치 매개 변수 ($1, $2 등)로 변환합니다.