파일 이름에서 공백, 하이픈 및 밑줄을 삭제 하시겠습니까?


10

디렉토리의 모든 파일 또는 선택한 파일에서 공백, 하이픈 및 밑줄을 삭제하는 좋은 명령은 무엇입니까?

Thunar 사용자 지정 동작과 함께 다음 명령을 사용하여 파일 이름을 슬러그 화합니다.

for file in %N; do mv "$file" "$(echo "$file" | tr -s ' ' | tr ' A-Z' '-a-z' | tr -s '-' | tr -c '[:alnum:][:cntrl:].' '-')"; done

그러나이 명령은 공백을 대시 / 하이픈 및 소문자 대문자로만 바꿉니다.

터미널에서 다음 명령을 사용하여 폴더의 수천 개의 파일 이름에서 공백을 삭제했으며 매우 빠르게 작동했습니다.

 rename "s/ //g" *

다시 말하지만 공백 만 삭제하고 하이픈 / 대시 및 밑줄도 삭제하지 않습니다.

이상적으로는 파일 이름에 공백, 하이픈 / 대시 및 밑줄을 원하지 않습니다. 선택한 파일에서 Thunar 사용자 정의 작업과 함께 명령을 사용할 수 있다면 좋을 것입니다.


2
제안 된 많은 솔루션이 가지고있는 한 가지 문제는 파일을 mv하기 전에 "새"이름의 존재를 올바르게 확인하지 않는 것입니다. 그렇게하지 않으면 많은 문제의 잠재적 원인이 될 수 있습니다.
mdpc

그것을 확인하기 위해 John1024의 명령을 수정할 수 있습니까?
user8547

@ user8547rename -i "s/[-_ ]//g" *
Sparhawk

Sparhawk에게 감사합니다. 또한,이를 Thunar 사용자 정의 조치로 사용하려는 사용자의 경우 Thunar 명령은 다음과 같습니다. file in % N; mv "$ file" echo $file | sed -e 's/[ _-]//g'; 완료
user8547

답변:


11

패키지 rename와 함께 제공 되는 버전 perl은 정규식을 지원합니다.

rename "s/[-_ ]//g" *

또는

rename -i "s/[-_ ]//g" *

-i플래그가 편리해집니다 rename대신 자동으로 덮어 쓰기의 대상이 이미 존재하는 경우 프롬프트 대화 형 모드를 사용합니다.

Perl의 이름 변경은 때때로이라고 prename합니다.

펄의 이름 바꾸기와 유틸리티 리눅스의 이름 바꾸기

데비안과 유사한 시스템에서 perl의 이름 바꾸기가 기본값 인 것으로 보이며 위의 명령이 작동해야합니다.

일부 배포판에서는 renameutil-linux 의 유틸리티가 기본값입니다. 이 유틸리티는 Perl과 완전히 호환되지 않습니다 rename.

  • 먼저 : Perl 's rename가 name 아래에 있는지 확인하십시오 prename.

  • 데비안 : Perl의 이름 바꾸기가 기본값이어야합니다. 로도 제공됩니다 prename. 그러나 rename실행 파일은 제어하에 있으며 /etc/alternatives다른 것으로 변경되었을 수 있습니다.

  • archlinux : Run pacman -S perl-rename및 명령은로 사용할 수 있습니다 perl-rename. 보다 편리한 이름을 위해 별명을 작성하십시오. (모발 끝 : ChiseledAbs)

  • 맥 OSX가 에 따르면 이 답변 , rename사제를 통해 사용 OSX에 설치할 수 있습니다 :

    brew install rename 
  • 직접 다운로드 : rename Perl Monks에서도 제공됩니다.

     wget 'http://www.perlmonks.org/?displaytype=displaycode;node_id=303814' -O rename

나는 그것이 rename당신이 말하는 것에 달려 있다고 생각합니다 . 에서 하나의 폴더의 유틸리티 - 리눅스 -2.24.2-1.fc20.x86_64는 정규 표현식을 지원하지 않습니다.
Cristian Ciupitu

1
@CristianCiupitu 방금 찾은 이름 바꾸기 버전에 대한 매뉴얼 페이지를 확인했습니다. 인수에 따라 renameOP가 사용중인 perl버전 은 버전이 아니라 버전과 비슷합니다 util-linux.
John1024

레코드의 경우이 rename페이지는 util-linux 버전 의 매뉴얼 페이지입니다 . 어쨌든, 그 메모 외에도 중요한 것은 OP가 그의 대답을 얻었 기 때문입니다 (그리고 당신은 나에게서 찬성 :-D).
Cristian Ciupitu

@CristianCiupitu 찾아 주셔서 감사합니다. +1로 다시 돌아옵니다.
John1024

1
@ John1024 archlinux,하지만 어떻게 알았는지, 그냥 가면 pacman -S perl-rename별칭을 사용할 수 있다고 생각합니다.
ChiseledAbs


4

계산하지 mv, 당신은 정말 전혀 이에 대한 외부 공정이 필요하지 않습니다 - 당신은 할 수 종류 단지의 그들.

ifsqz() ( LC_ALL=C sqz=$1
    isf() { [ -e "$1" ] || [ -L "$1" ] ; }  
    set -- * ; set -f
    for f do isf "$f" || break
    IFS=$sqz; set -- $f; IFS=
    isf "$*" || mv -- "$f" "$*"
    done
)

그럼에도 불구하고 mv파일 당 호출 을 의미 하므로 아마도 rename더 좋습니다. 이것은 단지 주어진 POSIX 작업을해야하지만 mv$PATH와 POSIX 쉘.

그래서 저는 이것에 대한 일종의 미친 데모를 생각해 냈습니다. 테스트 세트는 다음과 같이 생성됩니다.

tee - - - - <<CGEN |\
dd cbs=90 conv=unblock |\
sed 'G;$!N'";s/^/touch -- '/;s/$/'/" |sh
$( #BEGIN CGEN
   LC_ALL=C
   i= n='"$((i=((i=i+1)==10||i==39||i==47)>0?(i+1):i))"'
   printf '%b -_   ---___'  $(
   IFS=0; eval \
       printf '"\\\\%04o\\\\%04o "' "$(
       printf "$n"' "$i" '%s $(
       printf %.252d
#END
))"))
CGEN

우선 위의 명령이 다른 방법으로 더 쉽게 얻을 수있는 결과를 생성한다는 것을 인정할 것입니다. 그러나 다른 방법을 가능성이 함께 할 수있는 것뿐만 아니라 보여주지 것 $IFS조금 (병?) 상상력입니다.

따라서 첫 번째 비트는 매우 간단합니다.

  • tee 입력의 5 사본을 파이프로 보냅니다. CGEN

  • dd 블록 당 90 바이트의 줄 바꿈으로 입력을 차단하고 파이프를 ...

  • sed2 개의 \newline 문자에서 해당 블록 중 2 개를 결합 '하고 결과를 작은 따옴표로 묶고 touch --모든 줄주기마다 문자열 을 앞에 추가하여 ...

  • sh 그런 다음 모든 입력을 쉘 명령으로 실행합니다.

#CGEN비트하지만 ... 음, 간단하게 ...

  • 하단 printf은 252 0을 인쇄합니다

  • last from next는 252 개의 ''null-string 인수를 수신 하고 각각의 인쇄에 대해 $n그 뒤에 문자열 이 뒤 따릅니다." $i "

  • eval그 해석의 printf결과를 한 조각의 백 슬래시가 앞에 붙인 8 진수로 인쇄하기 전에 다음의 인수를 해석합니다.

  • 마지막 printf은 한 번에 8 진수 2의 바이트 값을 인쇄 한 다음 -_ ---___각 쌍 의 문자열 을 인쇄합니다.

  • $n$i10, 39 또는 47의 값을 건너 뛰는 것을 제외하고 모든 평가에 대해 1 씩 증가하는 방정식으로 초기화됩니다 ( 각각 ASCII 10 진수의 \newline, '작은 따옴표 및 /슬래시).

최종 결과는 작은 따옴표 (하나 이상의 sed s///문 을 피하기 위해 건너 뛰기 )/슬래시를 제외하고 1에서 255까지 내 문자 세트의 모든 바이트를 포함하는 실제로 추악한 파일 이름이 많은 디렉토리 입니다. 해당 파일 이름은 다음과 같습니다.

(set -- *; printf '%s\n\n##############\n\n%s\n' "${9}" "${34}")  | cat -A

   ---___ww -_   ---___xx -_   ---___yy -_   ---___zz -_   ---___{{ -_   ---___|| -_   ---$
$
___}} -_   ---___~~ -_   ---___^?^? -_   ---___M-^@M-^@ -_   ---___M-^AM-^A -_   ---___M-^BM-^B -_   ---___M-^CM-^C$
$
##############$
$
 -_   ---___M-ZM-Z -_   ---___M-[M-[ -_   ---___M-\M-\ -_   ---___M-]M-] -_   ---___M-^M-^ -_   ---___M-_M-_ -_$
$
---___M-`M-` -_   ---___M-aM-a -_   ---___M-bM-b -_   ---___M-cM-c -_   ---___M-dM-d -_   ---___M-eM-e -_   ---___$

이제이 파일들에 대한 데이터를 얻을 것이다 :

chksqz() ( LC_ALL=C sqz=$1
    set -- * ; set -f ; IFS= ; tc="$*"
    printf '#%s\n' \
        "There are $# files in this test directory." \
        "All filenames combined contain a total of ${#tc} bytes."
    IFS=$sqz ; set -- $* ; IFS= ; sc="$*"  
    printf "%s '$sqz'" \
        "#Of which ${#sc} bytes are not"\
        " and $((${#tc}-${#sc})) bytes are"
    set +f ; unset IFS
    printf ".\n#%s\n#Total:\t%d\n#Other:\t%d\n#'$sqz':\t%d\n" \
        "And to confirm these figures:" \
        $(  printf %s * | wc -c 
            printf %s * | tr -d "$sqz" | wc -c
            printf %s * | tr -dc "$sqz" | wc -c
))
chksqz '_ -'

산출

#There are 101 files in this test directory.
#All filenames combined contain a total of 17744 bytes.
#Of which 2692 bytes are not '_ -' and 15052 bytes are '_ -'.
#And to confirm these figures:
#Total: 17744
#Other: 2692
#'_ -': 15052

확인. 이제 마지막으로 행동하십시오.

ifsqz '_ -'
chksqz '_ -'

산출

#There are 101 files in this test directory.
#All filenames combined contain a total of 2692 bytes.
#Of which 2692 bytes are not '_ -' and 0 bytes are '_ -'.
#And to confirm these figures:
#Total: 2692
#Other: 2692
#'_ -': 0

성공! 당신은 자신을 볼 수 있습니다 :

ls

????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????
??????????????????????
????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
??????????????????????????
???????????????????????????
???????????????????????????
???????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
????????????????????????????
??????????????????????????
????????????????????????
????????????????????
??????????????????
????????????????????????????
??
????????????????????????????
??????????????????????????
????????????????????????????
????????????????????????????
????????????????????!!""##
??????????????????!!""##$$
????????????????!!""##$$%%
????????????!!""##$$%%&&((
????????!!""??##$$%%&&(())
$$%%&&(())**??++,,..0011
%%&&(())**++??,,..00112233
&&(())**++,,??..0011223344
))**++,,..??0011223344556
**++,,..00??11223344556677
22334455667788??99::;;<<==>>
445566778899??::;;<<==>>??@@
5566778899::;;??<<==>>??@@AA
6778899::;;<<??==>>??@@AABB
8899::;;<<==??>>??@@AABBCCDD
\\]]^^``aa??bbccddeeffgghh
]]^^``aabbc??cddeeffgghhii
^^``aabbccdd??eeffgghhiijj
??@@AABBCCDDEE??FFGGHHIIJJKK
AABBCCDDEEFF??GGHHIIJJKKLLM
BBCCDDEEFFGG??HHIIJJKKLLMMNN
CCDDEEFFGGHHII??JJKKLLMMNNOO
EEFFGGHHIIJJ??KKLLMMNNOOPPQQ
ffgghhiijjkk??llmmnnooppqqrr
gghhiijjkkllmm??nnooppqqrrss
iijjkkllmmnn??ooppqqrrsstt
jjkkllmmnnoo??ppqqrrssttuuvv
kkllmmnnooppqq??rrssttuuvvww
LLMMNNOOPPQQRR??SSTTUUVVWWXX
MNNOOPPQQRRSS??TTUUVVWWXXYY
OOPPQQRRSSTT??UUVVWWXXYYZZ[[
PPQQRRSSTTUUVV??WWXXYYZZ[[\\
RRSSTTUUVVWW??XXYYZZ[[\\]]
ssttuuvvwwxx??yyzz{{||}}~~??
ttuuvvwwxxyyz??z{{||}}~~????
uuvvwwxxyyzz{{??||}}~~??????
wwxxyyzz{{||??}}~~??????????
xxyyzz{{||}}~~??????????????
YYZZ[[\\]]^^??``aabbccddee
ZZ[[\\]]^^``??aabbccddeeff

2
의 창조적 인 사용을위한 1 IFS+printf
John1024

@ John1024-정말 재미있는 점 :set -- 'some arbitrary' args; eval printf '"%s\n"' "$(IFS=0; printf ' "$@" %s' $(printf %025d))"
mikeserv

1
new="$(IFS=" -_"; printf %s $1)"서브 쉘을 포크하고 (ksh93 제외) 테일링 개행에 문제가 있습니다. 또 다른 옵션은 사용하는 것입니다 IFS=' -_'; set -- $1; IFS=; new="$*"(그리고 while 루프를 for 루프로 변경)
Stéphane Chazelas

1
[ -e x ]x존재하지 않거나 액세스 할 수없는 파일에 대한 심볼릭 링크 인 경우 false를 반환 합니다.
Stéphane Chazelas

1
멋진 껍질 쿵푸!
카운터 모드

2

펄이있는 경우 일반적으로 이름이 바뀝니다. 넌 할 수있어:

> type rename
rename is /usr/bin/rename

이 스크립트가 어떻게 작성되는지 보여줍니다.

> cat /usr/bin/rename | head -n 5 #firt 5 lines for example
#!/usr/bin/perl -w
#
#  This script was developed by Robin Barker (Robin.Barker@npl.co.uk),
#  from Larry Wall's original script eg/rename from the perl source.
#

이 스크립트는 -i 플래그를 지원하지 않지만 (이것은 내 시스템의 버전입니다), 아마도 여러분의 지원합니다. 인수는 어떻습니까? 첫 번째는 PCRE 형식의 정규 표현식이며 필터처럼 작동하고 입력 이름을 출력 이름으로 수정합니다. 별표 '*'로 제공 한 입력 이름 목록입니다. 예를 들어,

> cd /tmp
> rename 's/ //g' *

실제 '*'에서 다음과 같이 확장 할 수 있습니다.

> rename 's/ //g' file1 file2 file3 othe files found in current directory

실제로 개수가 큰 파일이 있으면 함정에 빠지게됩니다. 쉘은 시스템이 허용하는 것보다 더 긴 라인을 확장합니다. find 또는 xargs를 사용하여 해결 방법을 수행 할 수 있습니다. 'find'를 사용하면 이름이 디렉토리에있는 파일 수와 같은 횟수로 호출되므로 문제가 발생합니다. -r 옵션과 함께 xargs를 사용하는 것이 좋습니다. 하나의 이름 바꾸기 호출은 많은 파일을 수정합니다. 예를 들면 다음과 같습니다.

> ls | xargs -r rename 's/ //g'   #thats all, names will be appended at the end of this command.

마지막 문제는 무엇을 의미합니까?

's/ //g'

이것은 이름 수정을위한 정규식입니다. 첫 번째 '/'뒤에 공백이 있습니다. 이것은 감지되고 두 번째 '/'다음에 문자열로 대체됩니다. 그러나 세 번째 '/'로 끝나는 빈 문자열이 있으면 공백이 아무것도 대체되지 않습니다. 옵션 'g'는이 표현을 반복적으로 만듭니다. expression은 모든 이름을 처음부터 끝까지 걸으며 모든 공백을 감지합니다.

그러나 탭 문자 나 다른 '백색'문자가 있다면 어떻게해야합니까? 이 '\ s'를 대체합니다. 다른 불필요한 캐릭터는 무엇입니까? 간단히 표현에 추가하십시오. 예를 들어 대괄호로 모두 닫습니다.

's/[\s_-]//g'

이게 전부입니다. 유사성이 보입니까? 나는 당신이 man perlrequick과 man perlretut을 읽어야한다고 생각합니다. 이것은 정규 표현식이 어떻게 작동하는지 설명합니다. 필요한 경우 자체 스크립트에서 rename 명령을 사용할 수 있습니다.


1

다음 sh쉘 루프는 기존 파일을 덮어 쓰지 않도록주의하면서 현재 디렉토리의 파일 이름에서 모든 공백, 밑줄 및 대시를 제거합니다.

for f in *; do
    test -f "$f" || continue
    nf=$( echo "$f" | tr -d ' _-' )
    ! test -e "$nf" && echo mv "$f" "$nf"
done

들어 bashksh, 그리고 논리와 좀 더 자세한되고 :

for f in *; do
    if [[ -f "$f" ]]; then
        nf=$( tr -d ' _-' <<<"$f" )
        if [[ ! -e "$nf" ]]; then
            echo mv "$f" "$nf"
        fi
    fi
done

echo원하는 작업을 수행 할 때 확실하게 제거하십시오 .

tr명령 (삭제됩니다 -d지정된 문자 세트에) 모든 문자를 ( ' _-'). 세트의 맨 처음이나 끝에 대시를 사용하는 것이 중요합니다. 그렇지 않으면 문자 범위로 해석됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.