Deepin(Debian 기반) 시스템에 다음과 같은 비디오 파일이 포함된 디렉토리가 있습니다.
SL Benfica - Match 1 vs FC Porto.mp4
SL Benfica - Match 2 vs FC Porto.mp4
...
SL Benfica - Match 20 vs FC Porto.mp4
...
SL Benfica - Match 100 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4
중간에 있는 숫자 앞에 0을 추가하여 다음과 같이 정렬하고 싶습니다.
SL Benfica - Match 001 vs FC Porto.mp4
SL Benfica - Match 002 vs FC Porto.mp4
...
SL Benfica - Match 020 vs FC Porto.mp4
...
SL Benfica - Match 100 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4
모드에 의존하지 않는 일반 명령을 찾고 있습니다. 5와 20과 같은 숫자를 검색하여 파일 이름의 어느 위치나 파일 이름의 끝이나 시작 부분에서도 005와 020으로 변경하면 됩니다.
답변1
사용할 수 있습니다 perl-rename
(Debian 기반 시스템에 설치할 수 있어야 함 sudo apt install rename
). 다음 파일을 입력으로 사용하십시오.
$ ls -1
'anotherFile.m4a'
'file 1 with 12 many 100 numbers 3.mp4'
'SL Benfica - Match 101 vs FC Porto.mp4'
'SL Benfica - Match 20 vs FC Porto.mp4'
'SL Benfica - Match 2 vs FC Porto.mp4'
다음을 실행할 수 있습니다.
rename 's/(\d+)(?=.*\.)/sprintf("%03d",$1)/eg' *
이렇게 하면 이름이 다음과 같이 변경됩니다.
'anotherFile.m4a'
'file 001 with 012 many 100 numbers 003.mp4'
'SL Benfica - Match 002 vs FC Porto.mp4'
'SL Benfica - Match 020 vs FC Porto.mp4'
'SL Benfica - Match 101 vs FC Porto.mp4'
어떻게 100
변경되지 않고 나머지가 채워지는지 확인하세요. 또한 4의 .m4a
합 은 mp4
영향을 받지 않습니다.
중요한-n
: 파일 이름이 실제로 바뀌기 전에 어떤 일이 일어나는지 보려면 먼저 명령을 실행하십시오 .
rename -n 's/(\d+)(?=.*\.)/sprintf("%03d",$1)/eg' *
\d+
하나 .
이상의 숫자( ) 앞에 하나 이상의 숫자( )를 찾는 정규식입니다 ?=.*\.
. 이는 내선 번호에 있는 번호가 변경되는 것을 방지하기 위한 것입니다. 그러나 파일 이름에 확장자가 없으면 작동하지 않습니다. 이와 같은 파일이 있는 경우 다음을 사용하여 모든 숫자를 입력하세요.
rename 's/(\d+)/sprintf("%03d",$1)/eg' *
는 대체 연산자이며 로 s/old/new/
대체됩니다 . 여기서는 괄호 안에 있으므로 일치하는 것은 무엇이든 됩니다.old
new
(\d+)
캡처됩니다$1
그러면 교체품 오른쪽에서 사용할 수 있습니다. 따라서 숫자를 0이 채워진 숫자로 바꿉니다( 0으로 채워진 숫자는 길이가 3이 될 때까지 sprintf("%03d", $number)
인쇄됩니다 ). $number
마지막으로 이 플래그를 e
사용하면 표현식(여기 sprintf
) 을 사용 g
하고 대체 항목을 전역으로 만들어 입력 줄(파일 이름)의 모든 일치 항목에 적용할 수 있습니다.
번호에 3개 이상의 0이 추가된 경우 3-0 패딩으로 잘립니다. 그래서 file 00000001.mp3
그것은 될 것입니다 file 001.mp3
.
답변2
그리고 zsh
:
autoload -Uz zmv # best in ~/.zshrc
zmv -n '(*).mp4' '${1//(#m)<->/${(l[3][0])MATCH}}.mp4'
만족스러우면 삭제 -n
(테스트 실행)합니다.
zmv
zsh glob 패턴에 따라 파일 이름을 바꿉니다. 이는(*).mp4
로 끝나는 파일 이름과 일치하며.mp4
앞의 부분.mp4
은 다음과 같습니다.캡처됩니다그래서$1
대용으로 사용할 수 있습니다.${1//pattern/replacement}
:ksh 연산자는 인수(여기서$1
) 확장 시 대체를 수행합니다.- 이것은 zsh 모드
pattern
입니다 . 대체 와 같이 일치하는 텍스트를 사용할 수 있게 만드는 것은 숫자 일치 연산자 의 가장 간단한 형태 로, 1개 이상의 십진수 시퀀스와 일치합니다. 와 동일합니다 .(#m)<->
extendedglob
(#m)
$MATCH
<->
<x-y>
[0-9]##
${(l[3][0])param}
인수 확장 플래그를 사용하여l[length][padstring]
0에서 길이 3까지의 확장을 왼쪽으로 채웁니다$MATCH
(또한 숫자를 길이 3으로 자릅니다).
약간 복잡해지기는 하지만 잘림을 방지하는 것이 가능합니다.
zmv -n '(*).mp4' '${1//(#m)<->/${(l[$#MATCH > 3 ? $#MATCH : 3][0])MATCH}}.mp4'
패딩 + 길이를 3으로 자르는 대신 최대 3인 길이와 패딩할 문자열의 길이까지 패딩 + 잘립니다. 또는 max()
자동 로드 가능한 함수에서 수학 함수를 사용할 수 있습니다 zmathfunc
.
autoload -Uz zmv zmathfunc; zmathfunc
zmv -n '(*).mp4' '${1//(#m)<->/${(l[max(3, $#MATCH)][0])MATCH}}.mp4'
답변3
GNU sed를 사용하면 다음을 수행할 수 있습니다(확장 없이도):
sed -E \
-e 'h;s/(.*)(\.[^.]*$)/\2/;ta;z;:a;x;s//\1/' \
-e 's/([0-9]{1,})/\n000\1\n/g' \
-e 's/\n[0-9]*([0-9]{3})\n/\1/g' \
-e 'G;s/\n//g' file
루프는 없고 정규식만 사용됩니다.
첫 번째 정규식은 일치합니다
'h;s/(.*)(\.[^.]*$)/\2/;ta;z;:a;x;s//\1/'
확장을 예약된 공간(있는 경우)에 배치합니다. 나머지는 패턴 공간에 남겨두세요.'s/([0-9]{1,})/\n000\1\n/g'
각 숫자 스트림을 별도의 줄에 배치하고 그 앞에 3개의 0을 추가합니다.
앞에 0이 있고 자체 줄에 있도록 수정하려는 각 숫자를 확장한 후 다음을 수행합니다.
's/\n[0-9]*([0-9]{3})\n/\1/g'
각 숫자 행에서 마지막 3자리를 추출합니다.'G;s/\n//'
시작 시 캡처된 확장을 다시 연결합니다.
소스 목록이 다음과 같은 경우:
➤ cat file
1- 23.m2
ATestFile.mp4
SomeFile.m4a
AFileWithNumbers23inside.mp4
File 1 with 12 some 100 numbers 3.mp4
SL Benfica - Match 1 vs FC Porto.mp4
SL Benfica - Match 2 vs FC Porto.mp4
SL Benfica - Match 20 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4
결과는 다음과 같습니다:
001- 023.m2
ATestFile.mp4
SomeFile.m4a
AFileWithNumbers023inside.mp4
File 001 with 012 some 100 numbers 003.mp4
SL Benfica - Match 001 vs FC Porto.mp4
SL Benfica - Match 002 vs FC Porto.mp4
SL Benfica - Match 020 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4
따라서 파일 이름을 바꾸려면(파일 이름에 개행 문자가 포함되어서는 안 되며 확장자 뒤에 점이 와야 합니다):
#!/bin/bash
for old in *; do
new=$( printf '%s\n' "$old" |
sed -E \
-e 'h;s/(.*)(\.[^.]*$)/\2/;ta;z;:a;x;s//\1/' \
-e 's/([0-9]{1,})/\n000\1\n/g' \
-e 's/\n[0-9]*([0-9]{3})\n/\1/g' \
-e 'G;s/\n//'
);
if [[ ! -f $new ]]; then
echo \
mv "$old" "$new";
fi
done
스크립트가 만족스러우면 삭제 echo
하여 실제로 파일을 변경하세요.
답변4
이 시도
$ ls SL*mp4 | awk -v mvCmd='mv "%s" "%s"\n' '{ old=$0; $5=sprintf("%3.3d",$5); printf mvCmd,old,$0 }'
새 파일 이름이 괜찮으면 명령을 다시 실행하고 출력을 bash와 같은 셸로 파이프하세요.
이 명령은 원래 파일 이름(이전)을 저장하고 다섯 번째 열($5)을 printf의 열 중 하나(3개의 숫자, 소수점 없음, 0으로 시작)로 바꾼 다음 이전 이름과 새 이름 주위에 따옴표를 사용하여 mv를 인쇄합니다(교체된 이름 지정). ) 명령.
awk에는 기본적으로 파일 이름 바꾸기 명령이 없기 때문에 출력을 bash로 파이프해야 합니다.