이에 대한 온라인 문서가 많이 있으며 bash
매뉴얼 페이지도 매우 훌륭합니다. 그럼에도 불구하고 이것이 왜 작동하지 않는지 이해하지 못합니다. 아무래도 뭔가 빠진 것 같은데...
file010
, file020
... 라는 이름의 100개 파일이 있는 디렉토리가 있습니다 file1000
. 나는 그것들의 이름을 new00..99
using 으로 바꾸길 원합니다 mv
( mvg
실제로는 둘 다 동일한 출력을 갖습니다). 다음 중 하나를 실행하면 target 'new99' is not a directory
(항상 마지막 항목)을 얻습니다.
내가 무엇을 놓치고 있나요?
id@machine ~/temp/test ls
file010 file090 file160 file240 file320 file400 file480 file560 file640 file720 file800 file880 file960
file020 file100 file170 file250 file330 file410 file490 file570 file650 file730 file810 file890 file970
file030 file1000 file180 file260 file340 file420 file500 file580 file660 file740 file820 file900 file980
file040 file110 file190 file270 file350 file430 file510 file590 file670 file750 file830 file910 file990
file050 file120 file200 file280 file360 file440 file520 file600 file680 file760 file840 file920
file060 file130 file210 file290 file370 file450 file530 file610 file690 file770 file850 file930
file070 file140 file220 file300 file380 file460 file540 file620 file700 file780 file860 file940
file080 file150 file230 file310 file390 file470 file550 file630 file710 file790 file870 file950
id@machine ~/temp/test mv {*,new{00..99}}
/usr/local/bin/mvg: target 'new99' is not a directory
✘ id@machine ~/temp/test mv {file{010..1000..10},new{00..99}}
/usr/local/bin/mvg: target 'new99' is not a directory
✘ id@machine ~/temp/test mv {file*,new{00..99}}
/usr/local/bin/mvg: target 'new99' is not a directory
답변1
당신은 무엇을 놓치고 있습니까? mv
작동 방식 .
정확히 2개의 파일을 제공하는 경우 첫 번째 파일 이름을 두 번째 파일 이름으로 바꿉니다.
파일이 2개 이상인 경우 마지막 인수는 디렉터리로 처리되며 이전 인수는 모두 디렉터리로 이동할 파일입니다.
인용하다매뉴얼 페이지.
파일 이름을 바꾸려면 루프가 필요합니다.
i=0
for file in *; do
mv -v "$file" "$(printf 'new%02d' $i)"
((i++))
done
아이디어: 파일이 100개가 넘으면 어떻게 될까요? 하드 코딩을 피하는 방법은 무엇입니까 %02d
?
files=(*)
num=$(( ${#files[@]} - 1 ))
size=${#num}
for idx in "${!files[@]}"; do
mv -v "${files[idx]}" "$(printf 'new%0*d' $size $idx)"
done
답변2
rename 100 files 를 사용하려면 각 개별 파일의 이름을 바꾸려면 100번 mv
호출해야 합니다 . mv
실질적인 해결책은 없습니다.
file010
숫자 순서대로 파일을 반복하려면 다음을 file1000
사용할 수 있습니다.
for name in file{010..990..10} file1000
do
# rest of code goes here
done
문자열 등 으로 최대 10 단계까지 {010..990..10}
확장할 수 있는 중괄호 확장 입니다 . 이러한 각 문자열에는 string 접두사가 붙습니다 . 숫자가 패턴에 맞지 않기 때문에 끝에 추가합니다(한 자리가 너무 깁니다) .010
020
030
990
file
file1000
루프에서 파일 이름을 바꾸려면 0부터 세기 시작하는 카운터를 유지할 수 있습니다. 그런 다음 새 파일 이름은 접두사로 구성되고 file
그 뒤에는 카운터의 현재 값에 따라 0으로 채워진 두 자리 정수가 옵니다.
위의 루프에 다음을 추가합니다.
count=0
for name in file{010..990..10} file1000
do
printf -v newname 'file%.2d' "$(( count++ ))"
mv -- "$name" "$newname"
done
for
또는 다음과 같이 중괄호 확장 대신 산술 루프를 사용할 수 있습니다 .
for (( i = 1; i <= 100; ++i )); do
printf -v name 'file%.3d' "$(( i * 10 ))"
printf -v newname 'file%.2d' "$(( i - 1 ))"
mv -- "$name" "$newname"
done
rename
대신 Perl 유틸리티를 사용하십시오 mv
.
rename -n -v 's/file(\d+)/sprintf "file%.2d", ($1\/10 - 1)/e' file*
이는 현재 디렉토리에서 일치하는 모든 파일 이름 에 Perl s///
(대체) 표현식을 적용합니다. file*
이 표현식은 하위 문자열 뒤의 숫자와 일치 file
하고 이를 사용하여 새 파일 이름 번호를 계산합니다(10으로 나누고 1을 뺍니다).
-n
실행 명령을 "실제"로 제거했습니다 ( -n
"시험 실행" 옵션임).
/e
대체 문자열을 평가 하지 않고 한 번만 언급하는 보다 깔끔한 변형 file
:
rename -n -v '/(file)(\d+)/; $_ = sprintf "%s%.2d", $1, ($2/10 - 1)' file*