다음과 같은 형식으로 많은 수의 파일 이름을 바꿔야 하는 상황이 발생했습니다.
file.csv
file_1.csv
file_2.csv
file_3.csv
file_4.csv
file_5.csv
file_6.csv
file_7.csv
file_8.csv
더 나은 정렬을 위해서는 다음이 필요합니다.
file_1.csv
file_2.csv
file_3.csv
file_4.csv
file_5.csv
file_6.csv
file_7.csv
file_8.csv
file_9.csv
즉, 첫 번째 파일의 이름을 수동으로 바꿀 수 있지만 나머지 " _#
" 파일 에 대해서는 +1
.
rename -n -v 's/_(.*)./.(\1+1)./'
하지만 얻었어
file_(1+1).csv
file_(2+1).csv
등.
_#
" " 파일을 일괄적으로 유지하는 간단한 방법이 있습니까 ?
추신, 아직은 더 좋습니다
file_01.csv
. . .
file_09.csv
file_10.csv
. . .
가능하다면.
고쳐 쓰다:
답변해 주셔서 감사합니다. 0으로 채워진 이름으로 이름을 바꾸었기 때문에 파일 이름이 충돌하지 않으므로 명령이 다음과 같이 단순화되었습니다.
touch file.csv file_{1..9}.csv
$ rename -v 's/^(file_)(\d+)(\.csv)$/$1 . (sprintf "%02i", $2 + 1) . $3/e' file_*
file_1.csv renamed as file_02.csv
file_2.csv renamed as file_03.csv
file_3.csv renamed as file_04.csv
file_4.csv renamed as file_05.csv
file_5.csv renamed as file_06.csv
file_6.csv renamed as file_07.csv
file_7.csv renamed as file_08.csv
file_8.csv renamed as file_09.csv
file_9.csv renamed as file_10.csv
마지막 두 파일 이름을 참고하세요.
file_09.csv
file_10.csv
답변1
Perl의 정규 표현식 수정자를 사용하여 /e
연산의 오른쪽을 s///
Perl 표현식으로 평가하도록 해야 합니다.
파일 이름도 정렬해야 합니다.취소가장 높은 번호의 파일 이름이 바뀌도록 번호 순서앞으로낮은 번호의 파일 이름(그렇지 않으면 파일 이름 충돌이 발생합니다. 기본적 -f
으로 rename
. 이를 위해 NUL 종료 입력에 대해 GNU find
with -print0
및 GNU sort
with를 사용 하고 역방향 버전(즉, "자연") 정렬을 사용하겠습니다. 옵션 은 두 번째 필드에서 정렬하는 데에도 사용됩니다.-z
-r
-V
-t _
-k 2
이름 바꾸기 옵션을 -d
사용하면 경로 이름의 파일 이름 부분만 이름이 바뀌고 -0
표준 입력에서 NUL로 구분된 파일 목록을 사용하게 됩니다.
예를 들어
$ touch file.csv file_{1..8}.csv
$ find . -name 'file_*.csv' -print0 |
sort -z -t _ -k2 -r -V |
rename -d -0 's/^(file_)(\d+)(\.csv)$/$1 . ($2 + 1) . $3/e'
$ mv file.csv file_1.csv
$ ls -l
total 5
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_1.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_2.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_3.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_4.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_5.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_6.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_7.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_8.csv
-rw-r--r-- 1 cas cas 0 Aug 21 15:22 file_9.csv
이것은 약간 단순화될 수 있지만 파일 이름을 바꾸면 안 되는 가능성을 피하기 위해 정규식 file_
에서 , 하나 이상의 숫자 및 확장자를 명시적으로 찾고 캡처하도록 만들었습니다 ..csv
파일 번호를 0으로 채우려면 이 sprintf
기능을 사용하십시오. 예를 들어
... | rename -0 -d -v 's/^(file_)(\d+)(\.csv)$/$1 . (sprintf "%02i", $2 + 1) . $3/e'
Reading filenames from file handle (GLOB(0x555555905960))
./file_8.csv renamed as ./file_09.csv
./file_7.csv renamed as ./file_08.csv
./file_6.csv renamed as ./file_07.csv
./file_5.csv renamed as ./file_06.csv
./file_4.csv renamed as ./file_05.csv
./file_3.csv renamed as ./file_04.csv
./file_2.csv renamed as ./file_03.csv
./file_1.csv renamed as ./file_02.csv
답변2
그리고 zsh
:
$ autoload -Uz zmv # best in ~/.zshrc
$ LC_ALL=C zmv -f -n '(file)(|_(<->))(.csv)(#qnOn)' '${1}_$(($3+1))$4'
mv -- file_11.csv file_12.csv
mv -- file_10.csv file_11.csv
mv -- file_9.csv file_10.csv
mv -- file_8.csv file_9.csv
mv -- file_7.csv file_8.csv
mv -- file_6.csv file_7.csv
mv -- file_5.csv file_6.csv
mv -- file_4.csv file_5.csv
mv -- file_3.csv file_4.csv
mv -- file_2.csv file_3.csv
mv -- file_1.csv file_2.csv
mv -- file.csv file_1.csv
또는 0
-padding을 사용하여 ${(l[2][0])...}
왼쪽 패딩 매개변수를 사용하여 플래그를 확장합니다.
$ LC_ALL=C zmv -fn '(file)(|_(<->))(.csv)(#qnOn)' '${1}_${(l[2][0])$(($3+1))}$4'
mv -- file_11.csv file_12.csv
mv -- file_10.csv file_11.csv
mv -- file_9.csv file_10.csv
mv -- file_8.csv file_09.csv
mv -- file_7.csv file_08.csv
mv -- file_6.csv file_07.csv
mv -- file_5.csv file_06.csv
mv -- file_4.csv file_05.csv
mv -- file_3.csv file_04.csv
mv -- file_2.csv file_03.csv
mv -- file_1.csv file_02.csv
mv -- file.csv file_01.csv
( 가능한 경우 삭제 -n
(시운전) ).
그러면 이 glob에서 생성된 파일의 이름이 변경됩니다. extendedglob
여기서:
<->
일련의 숫자와 일치합니다(<x-y>
지정된 범위 없이 연산자와 일치하는 십진 정수입니다).(#q...)
다음과 같이 glob 한정자를 지정합니다.n
: 숫자 전역 정렬 전환On
: 이름을 기준으로 역순으로 정렬합니다. 그래서file8
beforefile7
, 위의 Numericglobsort 덕분에file10
beforefile9
. 이는LC_ALL=C
정렬 알고리즘에서 합계가 무시되지 않도록 하기 위한 것입니다_
..
file.csv
file_1.csv
대체에서 $1
, ...에는 in 연산자와 유사한 패턴 으로 $2
각 쌍에 대한 일치 항목이 포함됩니다 .(
)
perl
s///
-f
는 온전성 검사를 비활성화하는 데 사용됩니다 . 즉 , 이미 존재하는 항목으로 이름이 변경된 것에 zmv
대해 불평합니다 (그때까지 이미 이름이 변경된 경우에도 ).file6.csv
file7.csv
file7.csv
file8.csv
rename
Perl을 사용 하여 이름을 바꿀 수 있지만 zsh
올바른 순서로 목록을 전달하려면 glob과 같은 것이 여전히 필요합니다.
$ (LC_ALL=C; rename -f -n '
s{^(file)(?:_(\d*))?(\.csv)\Z}{
"${1}_" . (($2 // 0) + 1) . $3}se
' file(|_<->).csv(nOn))
rename(file_11.csv, file_12.csv)
rename(file_10.csv, file_11.csv)
rename(file_9.csv, file_10.csv)
rename(file_7.csv, file_8.csv)
rename(file_6.csv, file_7.csv)
rename(file_5.csv, file_6.csv)
rename(file_4.csv, file_5.csv)
rename(file_3.csv, file_4.csv)
rename(file_2.csv, file_3.csv)
rename(file_1.csv, file_2.csv)
rename(file.csv, file_1.csv)
(($2 // 0) + 1)
예를 들어 패딩을 0 으로 바꿉니다 sprintf("%02d", ($2 // 0) + 1)
.
해당 파일이 없어 설치할 수 없지만 zsh
GNU 시스템을 사용하는 경우 bash
다음 명령을 사용하여 올바른 순서로 파일을 가져올 수 있습니다.
eval "files=(
$(
shopt -s extglob failglob
export LC_ALL=C
ls --quoting-style=shell-always -rvd file?(_+([0-9])).csv
)
)"
ls -rv
파일을 역버전 순서로 나열하려면 GNU를 사용하십시오 .
rename ... "${files[@]}"
그런 다음 위와 rename
동일한 코드를 사용하여 이름 바꾸기를 호출합니다.
여기서는 파일 이름이 매우 간단하고 일치하는 다른 파일이 없다고 가정하고 file*.csv
기본값을 사용하여 $IFS
이 작업을 수행할 수도 있습니다(여전히 GNU ls를 사용하지만 Bourne과 유사한 쉘을 사용함).
rename ... $(LC_ALL=C ls -rvd file*.csv)
답변3
한 가지 접근 방식은 다음과 같습니다.
set -- file_*.csv
while [ "$#" -gt 0 ]; do
set -- "$#" "$@"
mv -- "file_$1.csv" "file_$#.csv"
shift 2
done
mv file.csv file_1.csv
0으로 채워진 파일 이름을 유지하려면 mv
명령문을 다음과 같이 변경하십시오.
mv -- "file_$1.csv" "$(printf 'file_%02d.csv\n' "$#")"
mv file.csv file_01.csv
명령줄 인수가 엉망이 되는 것이 걱정된다면 함수 내에서 이 모든 작업을 수행하고 해당 함수를 호출할 수 있습니다.