너무 간단한 것 같았는데 완전히 당황했습니다. 말할 필요도 없이 나는 이것에 완전히 새로운 것입니다. 000
에서 까지의 파일 번호가 있는 디렉토리가 있습니다 020
. 1을 000
추가 하여 이 파일의 이름을 바꾸고 싶습니다 001
. 이상적으로는 명령을 사용 awk
하지만 조언을 주시면 감사하겠습니다.
접두사가 없으면 000
전체 이름입니다. 로 표시된 파일이 없습니다 021
.
답변1
zsh
대신 을 사용하면 bash
다음을 수행할 수 있습니다.
autoload -Uz
zmv -f -n '*(#qnOn)' '${f//(#m)<->/${(l[3][0])$((MATCH+1))}}'
현재 디렉터리의 파일 이름에 있는 각 숫자를 늘리고 길이를 0으로 채워 길이를 3으로 만듭니다. 예를 들어 또는 foo-1-2-003.ext
로 이름을 바꿉니다 foo-002-003-004.ext
.012
013
( 파일 전체가 숫자이거나, 0~20 사이의 파일 이름을 바꾸 거나 , 0~20 사이의 파일 이름을 3자리 숫자로 바꾸면 zmv -f -n '<->(#qnOn)' '${(l[3][0])$((MATCH+1))}'
충분합니다 .)<0-20>
<->
<0-20>~^[0-9](#c3)
대체 항목은 패턴과 함께 ksh
-style을 사용하여 계산 되어 일치하는 콘텐츠의 캡처 를 트리거 하고 임의의 십진수 시퀀스(의 무한한 형식 )와 일치합니다. 왼쪽 패딩 매개변수 확장 플래그는 패딩에 사용됩니다.${var//pattern/replacement}
(#m)<->
(#m)
$MATCH
<->
<3-12>
l[width][pad]
및 한정자를 사용하여 n
파일 목록을 이름의 역순으로 정렬하여 로 이름이 변경되기 전에 로 이름이 변경되었는지 확인합니다.O
n
n
On
q
file002
file003
file001
file002
여기에서 온전성 검사를 비활성화하면 일부 대상이 소스에서도 발견된다는 불만이 표시되지만 이는 -f
a와 파일이 모두 존재하는 경우 데이터 손실을 방지할 수 없음을 의미합니다.file1
file01
zsh는 없지만 bash가 있고 000~020이라는 이름의 파일이 있고 이름을 바꾸려는 파일인 경우(나중에 명시한 대로) 다음을 수행할 수 있습니다.
for file in {020..000}; do
printf -v new %03d "$(( 10#$file + 1 ))"
mv "$file" "$new"
done
{020..000}
(bash는 실제로 bash에서 복사된 zsh에서 복사되었으며 -v
코드는 두 셸 모두에서 작동하며 10#
따옴표는 필요하지 않습니다 zsh
.)
여기에서는 파일 이름이 꽤 길기 때문에 다음을 수행할 수도 있습니다.
ls -rq | LC_ALL=C awk '
/^[0-9]{3}$/ && $0 <= 20 {
printf "mv %s %03d\n", $0, $0+1
}' | sh
-q
(표준이지만 현재 busybox에서는 지원되지 않음 ls
) 이름에 개행 문자가 있는 파일이 있더라도 각 줄에 파일 이름이 있는지 확인합니다. LC_ALL=C
따라서 일치 하는 경우 [0-9]
에만 .0123456789
awk
mawk
[0-9]{3}
[0-9][0-9][0-9]
답변2
logrotate 파일과 같이 공백이 없으면 ls가 작업을 수행할 수 있으며 수학/awk는 필요하지 않습니다.
dest=021; ls -r|while read file; do mv $file $dest; dest=$file; done
dest가 항상 021이 아닌 경우 dest=$(printf "%03d" $(ls|wc -l)) 와 같은 것입니다.