다음 파일 목록을 고려하십시오.
$ touch index-{1,2,3,4,5,6,7,8,9}.txt
내가 그걸 바꾸고 싶다면아래에그래서 그들은 처음부터 시작합니다.비교적 쉬움:
$ rename --verbose 's/^index-([1-9])\.txt$/$1/; $_="index-" . ($_ - 1) . ".txt"' index-*.txt
man bash
이는 지정된 glob이 알파벳순으로 정렬되어 다음과 같이 이름이 바뀌기 때문에 작동합니다 index-1.txt
.index-0.txt
앞으로index-2.txt
로 이름이 변경되었습니다 index-1.txt
.
변경하려는 경우 실패합니다.위로, 또는 번호가 다음과 같은 경우다른 길이:
$ touch index-{10,11}.txt
$ rename --verbose 's/^index-([0-9]+)\.txt$/$1/; $_="index-" . ($_ + 1) . ".txt"' index-*.txt
index-10.txt not renamed: index-11.txt already exists
index-11.txt renamed as index-12.txt
index-1.txt not renamed: index-2.txt already exists
가능한 장기 수정 사항:
rename
충돌하는 옵션이 발생하지 않을 때까지 작업 순서를 다시 지정해 보십시오.rename
먼저 파일을 임시 디렉터리로 이동한 다음 새 이름으로 다시 이동하는 옵션입니다.rename
첫 번째 단계에서 원래 이름이나 새 이름과 충돌하지 않는 고유한 이름을 사용하여 두 단계로 파일 이름을 바꾸는 옵션입니다 .- 자연스러운 정렬을 하는 방법 +뒤집다Bash 전역 변수.
이 문제를 해결하는 쉬운 방법이 있나요?
답변1
일련의 이름 바꾸기가 어떤 순서로 이루어져야 하는지 결정하기 위한 일반적인 솔루션을 찾는 데 도움이 될 수 있는 Unix에는 잘 알려지지 않은 표준 명령이 있습니다.tsort
다음과 같은 파일에 수행할 이름 바꾸기 목록이 있다고 가정해 보겠습니다 renames.txt
(시연을 위해 해당 이름에 공백이 포함되어 있지 않다고 가정).
d a
e f
b e
a c
d
이름이 변경되기 때문에 먼저 이름을 변경해야 한다는 a
의미입니다 . 따라서 파일 이름을 바꿔야 하는 순서와 반대인 부분 정렬 순서가 있습니다.a
d
tsort
정렬 순서의 부분 목록에서 전체 정렬 순서를 유추하는 도구입니다. 루프가 있으면 오류를 반환하므로 해결책이 없는 상황을 감지하는 데 도움이 됩니다. 해당 입력을 적용하면 tsort
다음이 제공됩니다.
b
d
e
a
f
c
after 이후에 이름을 바꿔야 b
한다고 나와 있습니다 . 우리는 사용할 수 있습니다d
e
암소 비슷한 일종의 영양 tac
(일부 시스템에서도 사용 가능 tail -r
) 순서를 반대로 하려면:
c
f
a
e
d
b
그리고 이름 변경 목록에 추가하세요.
tsort renames.txt | tac | awk '
NR==FNR {
ren[$1] = $2
next
}
$1 in ren {
print "mv -i --", $1, ren[$1]
}' renames.txt -
이는 우리에게 다음을 제공합니다.
mv -i -- a c
mv -i -- e f
mv -i -- d a
mv -i -- b e
그런 다음 파이프라인을 통해 실행할 수 있습니다 sh
.
그러나 위의 코드는 루프를 감지하기 위해 위의 종료 상태를 확인하지 않았 tsort
으며 파일 이름에 특수 쉘 문자가 포함되어서는 안 되므로 강력하지 않습니다.
이것견고성독자를 위한 연습으로 남겼습니다 ;-)
답변2
더 나은 견고성을 위해 다시 작성된 @l0b0의 솔루션:
printf '%s\0' index-*.txt |
sort --zero-terminated --field-separator - --key 2rn |
xargs -0r rename --verbose '
s/^index-([0-9]+)\.txt$/$1/;
$_="index-" . ($_ + 1) . ".txt"'
솔루션을 자유롭게 추가해 주시면 답변을 삭제하겠습니다.
@l0bo의 솔루션은 Unix가 아닌 GNU 전용입니다(GNU는 Unix가 아님).
답변3
이는 위의 특정 사례에 적용됩니다.
rename --verbose 's/^index-([0-9]+)\.txt$/$1/; $_="index-" . ($_ + 1) . ".txt"' $(printf '%s\n' index-*.txt | sort --field-separator - --key 2n | tac)
하지만:
- 그것은 처리하지 않습니다공백파일 이름에
- 임의의 파일 이름의 경우 상황은 훨씬 더 복잡합니다.
답변4
맥락을 설명하자면, 타임랩스용 LapseIt Pro 앱을 사용하고 있었는데 어떤 이유로 중지되었다가 타임랩스를 다시 시작했지만 다음과 같은 다른 프로젝트 이름이 지정되었습니다.
Proj10_img0000000x
3000개 정도의 파일 이름을 모두 이전 프로젝트 Proj9_img0000000x로 바꾸고 마지막에 번호를 수정하여 프로젝트가 연속적인 이름 + 번호 피드를 가지도록 해야 모든 이미지를 하나의 프로젝트 비디오로 렌더링할 수 있습니다.
Proj10_img00000001 --> Proj10_img00003249를 Proj9_img00004325 --> Proj9_img00007574로 변경해야 합니다.
요약하면 최종 결과는 프로젝트 폴더 Proj9_img00000001 --> Proj9_img00007574에서 다음과 같습니다.
Mac OSX를 사용하는 경우(저는 Mojave를 사용하고 있습니다)
- Finder에서 수정할 모든 파일을 강조 표시합니다.
- 강조 표시된 파일 부분을 마우스 오른쪽 버튼으로 클릭하세요.
- "X 수량" 항목 이름 바꾸기를 선택하세요.
- "Finder 항목 이름 바꾸기" 팝업이 열립니다.
- 이 팝업을 사용하면 다른 편리한 옵션과 함께 쉽게 이름을 바꾸고 번호를 다시 매길 수 있습니다.
여전히 명령줄 grep/sed/awk/cut & find 명령을 보고 있지만 지금은 위의 내용이 작동합니다(게시하려면 최대한 빨리 비디오를 완료해야 합니다).