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

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

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

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 사용자 정의 작업과 함께 사용할 수 있다면 좋을 것입니다.

답변1

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

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

또는,

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

-i플래그는 rename대화형 모드를 사용하여 대상을 자동으로 덮어쓰는 대신 대상이 이미 존재하는지 묻는 메시지를 표시합니다.

Perl의 이름 바꾸기는 때때로 이라고 불립니다 prename.

Perl 이름 바꾸기 및 util-linux 이름 바꾸기

Perl 이름 바꾸기가 기본값인 Debian 계열 시스템에서는 위 명령이 작동합니다.

일부 배포판에서는 renameutil-linux의 유틸리티가 기본값입니다. 이 유틸리티는 Perl의 rename.

  • 모두:먼저 Perl rename이름을 사용할 수 있는지 확인하세요 prename.

  • 더반:Perl 이름 바꾸기는 기본값이어야 합니다. 로도 작동합니다 prename. 그러나 실행 파일이 rename제어되므로 /etc/alternatives다른 것으로 변경할 수 있습니다.

  • 아치 리눅스:Run 을 실행 pacman -S perl-rename하면 명령이 로 시작됩니다 perl-rename. 보다 편리한 이름을 사용하려면 별칭을 만드세요. (모자 팁: ChiseledAbs)

  • 애플 컴퓨터~에 따르면이 답변, rename다음을 통해 homebrew를 사용하여 OSX에 설치할 수 있습니다.

    brew install rename 
    
  • 다운로드: renamePerl Monks는 또한 다음을 제공합니다:

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

답변2

tr이 모든 명령을 다음과 같은 대체 명령으로 바꾸 겠습니다 sed.

for file in %N; do 
    mv "$file" "$(echo "$file" | sed 's/[ _-]//g')"
done

답변3

아니요 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 mvin $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

  • dd90바이트 블록당 개행 문자로 입력을 차단하고 다음으로 파이프합니다.

  • sed청크 중 2개를 두 개의 \newline 문자 로 연결하고 '결과를 작은따옴표로 묶은 다음 touch --출력을 파이핑하기 전에 각 줄 루프의 문자열 앞에 추가합니다... .

  • sh그런 다음 모든 입력을 쉘 명령으로 실행하십시오.

#CGEN그런데...뭐, 간단히 말하자면...

  • 하단에 printf252개의 0을 인쇄합니다.

  • 두 번째 항목은 252개의 빈 문자열 매개변수를 수신하고 각 매개변수에 대해 다음 문자열 ''의 내용을 인쇄합니다.$n" $i "

  • eval다음 printf인수를 해석하고 2개의 백슬래시가 앞에 오는 8진수로 해석 결과를 인쇄합니다.

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

  • $n방정식으로 초기화되고 $i평가할 때마다 1을 추가하지만 값 10, 39 또는 47을 건너뜁니다.(ASCII 10진수 \n줄바꿈, '작은따옴표 및 슬래시 각각)/

최종 결과는 내 문자 집합(작은따옴표 제외)의 1부터 255까지의 모든 바이트를 포함하는 매우 보기 흉한 파일 이름이 많이 포함된 디렉토리입니다.( 다른 설명을 피하기 위해 그냥 sed s///건너뛰었습니다 )그리고 /슬래시. 이러한 파일 이름은 다음과 같습니다.

(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

답변4

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

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

bash및 의 ksh경우 논리가 좀 더 자세합니다.

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' _-'

관련 정보