현재 디렉터리 및 하위 디렉터리에 있는 여러 파일의 이름을 바꾸는 스크립트

현재 디렉터리 및 하위 디렉터리에 있는 여러 파일의 이름을 바꾸는 스크립트

스크립트는 디렉터리/하위 디렉터리의 각 파일을 반복적으로 살펴보고(심볼릭 링크 건너뛰기) 파일 이름을 다음과 같이 대체해야 합니다.

  • 여러 개의 연속된 공백은 하나의 공백만 해당
  • 여러 개의 연속 _ 하나만 포함 _
  • 하나 이상의 밑줄과 하나 이상의 공백(밑줄은 하나만 포함)
  • 밑줄 다음에 - 밑줄만
  • - 뒤에 밑줄이 오고 밑줄만 나타납니다.
  • 여러 개의 연속된 "."에는 점이 1개만 있습니다.
  • 파일 접미사를 모두 소문자로 만듭니다(예: .PdF에서 .pdf로) 이는 단지 예일 뿐입니다.
  • @, $ 또는 !와 같은 문자를 제거하세요.

답변1

사용 find및 Perl rename:

참고: Perl은 다양한 Linux 배포판에서 , , 또는 .perl rename로도 알려져 있습니다 . 기능과 명령줄 옵션이 완전히 다르고 호환되지 않는 유틸리티와 혼동하지 마십시오 .file-renameperl-renameprenamerenameutil-linux

find . -type f -print0 |
  rename -n -0 '
    s/[\@\$!]//g;            # remove all @, $, and ! characters.

    # remove leading and trailing whitespace (if any) from filenames
    s/^\s+|\s*\z//sg;

    # change all runs of any whitespace to just one space
    s/\s+/ /sg;

    s/[- ]*([._])[- ]*/$1/g; # remove space(s) and - around _ and .

    s/\.\.+/./g;             # reduce multiple periods to just one
    s/__+/_/g;               # reduce multiple _ to just one
    s/_*\._*/./g;            # change _. and ._ to just .

    s=(\.[^./]*\z)=lc($1)=e; # lowercase filename suffixes
'

세 번째 대체 유형은 연속된 하나 이상의 공백 문자(실제 공백 문자, 탭, 줄 바꿈, 폼 피드 등 포함)를 단일 공백 ​​문자로 대체합니다. IMO는 요청한 것 이상이지만 파일 이름에서 공백 문자만 바꾸는 것보다 다양한 유형의 공백 문자를 모두 바꾸는 것이 더 유용할 수 있습니다. 원하는 내용이 아닌 경우 (공백 2개와 공백 1개) \s+로 변경하세요 +.+

네 번째 대체( ) s/[- ]*([_.])[- ]*/$1/g;는 또는 앞에 공백이나 _대시가 필요하지 않다고 가정합니다 .. 이는 귀하가 요청한 것보다 많지만 실제로 필요한 것보다 많은 경우 쉽게 변경할 수 있습니다.

관련하여 두 번째 대체는 _.및 로만 대체됩니다. 이렇게 하면 와 같은 파일 이름을 얻을 수 없습니다. 이와 같은 파일 이름을 원하면 이 줄을 제거하세요.._.foo_.bar_._pdf

마지막 대체의 정규식 수정자는 e대체가 Perl 코드(이 경우 lc()입력을 소문자로 만드는 함수)로 평가되도록 합니다.

참고: -n옵션의 이름을 변경하여 수행할 작업만 보여주는 시험 실행으로 만듭니다. 실제로 파일 이름을 바꾸려면 파일을 삭제 -n하거나 변경하여 -v자세한 출력을 얻으세요.

또한 원하는 경우 여러 줄 이름 바꾸기 스크립트를 하나의 길고 읽을 수 없는 줄로 압축할 수 있습니다(주석을 제거한 경우). #그러나 추가 줄 바꿈 및 들여쓰기를 사용하면 명령줄에서 읽기 및 편집이 더 쉬워집니다. 그리고 스크립트에서.

마지막으로 이것은 당신이 말할 때"디렉토리/하위 ​​디렉터리의 모든 파일 찾아보기(기호 링크 건너뛰기)"또한 이름 변경에서 디렉터리, 장치 노드, 명명된 파이프, 소켓 등을 제외하려고 합니다. 즉, 일반 파일만 이름이 변경됩니다.

일치하는 디렉터리의 이름도 바꾸려면 -type ffind변경 해야 합니다 \( -type f -o -type d \).

물론 원하는 find 조건자를 사용하여 검색을 구체화할 수 있습니다.

답변2

라는 유틸리티가 있습니다.디톡스이것은 많은 문제를 해결할 수 있습니다. 웹페이지에서:

  • 대문자 ASCII Latin-1(ISO 8859-1) 문자(즉, 왼쪽 및 오른쪽 큰따옴표)를 제거하거나 바꿉니다. 가능할 때마다 대체 문자가 사용됩니다(예: 위의 악센트가 있는 "A"가 "A"로 대체됩니다).
  • UTF-8로 인코딩된 유니코드 문자를 제거하거나 교체합니다. 이는 유니코드의 범위가 훨씬 더 넓다는 점을 제외하면 ISO 8859-1 번역과 동일한 방식으로 작동합니다.
  • 공백과 (,) 및 @와 같이 까다로울 수 있는 기타 문자를 제거하거나 교체합니다. 파일 이름 시작 부분의 "-"를 제거하십시오.
  • CGI 이스케이프된 ASCII 문자를 제거하거나 바꾸십시오. 즉, %20은 " "(그리고 "_")가 됩니다.
  • 초과된 "_" 및 "-"를 자릅니다.
  • 디렉터리 재귀, 시험 실행, 세부 목록.
  • 안전을 염두에 두고 설계되었습니다. 이미 존재하는 파일을 덮어쓰지 않으며 특수 파일은 일반적으로 건드리지 않습니다(그러나 요청할 수 있음).

답변3

그리고 zsh:

autoload -Uz zmv
zmv -n '(**/)(*)' '$1${${${${${2//[@\$!]}//[ _]##/_}//.##/.}//[-_]#_[-_]#/_}/%(#m).[^.]#/$MATCH:l}'

( 만족스러우면 -n시험 실행을 위해 제거하십시오 ).

이는 일부 ${param//pattern/replacemenet}연산자와 중첩됩니다.

  • ${2//[@\$!]}:( 파일의 기본 이름) @ $ !에서 모든 s를 제거합니다. $2공간이 생길 수 있으므로 먼저 이 작업을 수행 _하거나 -후속 단계에서 함께 압축해야 할 수도 있습니다.
  • ${...//[ _]##/_}: 위 결과에서 ##하나 이상의 공백( ) 또는 밑줄을 다음으로 대체합니다._
  • ${...//.##/.}: 위 결과에서 ##하나 이상의 ( ) 순서를 .다음으로 대체하십시오..
  • ${...//[-_]#_[-_]#/_}: 위 결과를 기준으로 0개 이상( #) _또는 -양면이 있는 항목을 삭제합니다.__
  • ${.../%(#m).[^.]#/$MATCH:l}: 수정자를 사용하여 소문자로 변환된 동일한 내용으로 끝 부분의 a( ) .와 일련의 s가 아닌 문자를 대체합니다(대체 시 일치 항목을 사용할 수 있도록 함)..%(#m)$MATCH:l

zmv디렉터리 깊이가 먼저 처리되고(해당 지점 이전에 나옴) 이름 바꾸기를 시작하기 전에 데이터가 손실되지 않았는지 확인하기 위한 일부 온전성 검사를 통해 교체가 수행됩니다.

예를 들어 다음과 같이 하십시오:

mv -- 'A _  - _  .. - b -c-d ..PDF' A_._b_c-d_.pdf

관련 정보