디렉토리의 모든 파일 또는 선택한 파일에서 공백, 하이픈 및 밑줄을 삭제하는 좋은 명령은 무엇입니까?
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 사용자 정의 작업과 함께 명령을 사용할 수 있다면 좋을 것입니다.
답변
패키지 rename
와 함께 제공 되는 버전 perl
은 정규식을 지원합니다.
rename "s/[-_ ]//g" *
또는
rename -i "s/[-_ ]//g" *
-i
플래그가 편리해집니다 rename
대신 자동으로 덮어 쓰기의 대상이 이미 존재하는 경우 프롬프트 대화 형 모드를 사용합니다.
Perl의 이름 변경은 때때로이라고 prename
합니다.
펄의 이름 바꾸기와 유틸리티 리눅스의 이름 바꾸기
데비안과 유사한 시스템에서 perl의 이름 바꾸기가 기본값 인 것으로 보이며 위의 명령이 작동해야합니다.
일부 배포판에서는 rename
util-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
답변
모든 tr
명령을 sed
대체 명령으로 바꿉니다. 예 :
for file in %N; do
mv "$file" "$(echo "$file" | sed 's/[ _-]//g')"
done
답변
계산하지 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 바이트의 줄 바꿈으로 입력을 차단하고 파이프를 … -
sed
2 개의\n
ewline 문자에서 해당 블록 중 2 개를 결합'
하고 결과를 작은 따옴표로 묶고touch --
모든 줄주기마다 문자열 을 앞에 추가하여 … -
sh
그런 다음 모든 입력을 쉘 명령으로 실행합니다.
#CGEN
비트하지만 … 음, 간단하게 …
-
하단
printf
은 252 0을 인쇄합니다 -
last from next는 252 개의
''
null-string 인수를 수신 하고 각각의 인쇄에 대해$n
그 뒤에 문자열 이 뒤 따릅니다." $i "
-
eval
그 해석의printf
결과를 한 조각의 백 슬래시가 앞에 붙인 8 진수로 인쇄하기 전에 다음의 인수를 해석합니다. -
마지막
printf
은 한 번에 8 진수 2의 바이트 값을 인쇄 한 다음-_ ---___
각 쌍 의 문자열 을 인쇄합니다. -
$n
는$i
10, 39 또는 47의 값을 건너 뛰는 것을 제외하고 모든 평가에 대해 1 씩 증가하는 방정식으로 초기화됩니다 ( 각각 ASCII 10 진수의\n
ewline,'
작은 따옴표 및/
슬래시).
최종 결과는 작은 따옴표 (하나 이상의 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
답변
펄이있는 경우 일반적으로 이름이 바뀝니다. 넌 할 수있어:
> 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 명령을 사용할 수 있습니다.
답변
다음 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
지정된 문자 세트에) 모든 문자를 ( ' _-'
). 세트의 맨 처음이나 끝에 대시를 사용하는 것이 중요합니다. 그렇지 않으면 문자 범위로 해석됩니다.