
다음과 같은 형식의 여러 파일이 포함된 폴더가 있습니다.
C Block Scan copy 1.pdf
C Block Scan copy 2.pdf
C Block Scan copy 3.pdf
C Block Scan copy 4.pdf
.
.
.
내가 겪고 있는 한 가지 문제는 내가 실행할 때 ls
Unix가 이를 다음과 같이 나열한다는 것입니다.
C Block Scan copy 1.pdf
C Block Scan copy 10.pdf
C Block Scan copy 11.pdf
C Block Scan copy 12.pdf
.
.
.
Unix가 (희망적으로) 다음과 같이 순서대로 나열할 수 있도록 숫자를 채우고 싶습니다.
C Block Scan copy 01.pdf
C Block Scan copy 02.pdf
C Block Scan copy 03.pdf
.
.
.
C Block Scan copy 09.pdf
C Block Scan copy 10.pdf
C Block Scan copy 11.pdf
C Block Scan copy 12.pdf
.
.
.
비슷한 문제가 있는 글을 발견했는데,파일 이름의 숫자를 고정 길이로 채우기, 그러나 내 사례에 해당 솔루션을 적용해 보았지만 제대로 작동하지 못했습니다. 내가 시도한 것은 다음과 같습니다.
for f in *.pdf; do
int=`basename $f .pdf | cut -d '.' -f 2`
new_name=`printf "file.%0.2i.pdf\n” $int`
[ ! -f $new_name ] && mv $f $new_name
done
나는 이것이 내 상황에 대한 그들의 솔루션을 맹목적으로 적용한 것임을 인정합니다. 기본 구문을 실제로 이해하지 못하고 아직 해당 게시물에 댓글을 달 수 있을 만큼 StackExchange 순위가 높지 않기 때문에 마음에 들지 않습니다. .
저는 쉘 스크립팅을 처음 접했기 때문에 구문의 의미에 대한 설명이 도움이 될 것입니다.
도움이 되신다면 저는 macOS Mojave 10.14.6을 사용하고 있으며 Brew가 설치되어 있습니다.
미리 감사드립니다.
답변1
( zsh
현재 macOS의 기본 사용자 셸):
autoload zmv # best in ~/.zshrc
zmv '(* )([0-9].pdf)' '${1}0$2'
답변2
그러면 현재 디렉터리에서 이름이 질문에 설명된 패턴을 따르는 모든 "*.pdf" 파일을 찾아 이름을 바꾸지만 숫자는 2자리로 채워집니다.
#!/usr/bin/env bash
shopt -s nullglob
for f in *[[:space:]][0-9].pdf; do
int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"
name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"
padded_int="$(printf "%02d\n" "$int")"
echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"
done
실제로 실행하려면 echo
먼저 제거 하고 원하는 대로 작동하는지 확인하기 위해 먼저 있는 그대로 실행하세요. 위 스크립트의 사용 예는 다음 위치에 저장됩니다 .mv
mv
pdf.sh
$ for i in {1..10}; do touch "C Block Scan copy $i.pdf"; done
$ ./pdf.sh
mv C Block Scan copy 1.pdf C Block Scan copy 01.pdf
mv C Block Scan copy 2.pdf C Block Scan copy 02.pdf
mv C Block Scan copy 3.pdf C Block Scan copy 03.pdf
mv C Block Scan copy 4.pdf C Block Scan copy 04.pdf
mv C Block Scan copy 5.pdf C Block Scan copy 05.pdf
mv C Block Scan copy 6.pdf C Block Scan copy 06.pdf
mv C Block Scan copy 7.pdf C Block Scan copy 07.pdf
mv C Block Scan copy 8.pdf C Block Scan copy 08.pdf
mv C Block Scan copy 9.pdf C Block Scan copy 09.pdf
첫 번째 줄:
#!/usr/bin/env bash
이 줄
shopt -s nullglob
세트널글로브 쉘 옵션 링크된 사이트에서도 설명되어 있습니다.
nullglob
If set, Bash allows filename patterns which match no files to
expand to a null string, rather than themselves.
패턴 기준과 일치하는 파일이 없는 경우 for 루프가 시작되지 않도록 방지해야 합니다.
for f in *[[:space:]][0-9].pdf; do
*[[:space:]][0-9].pdf
임의 개수의 문자, 공백, 한 자리 숫자로 구성된 이름을 가진 파일을 찾는 것을 의미하는 쉘 패턴입니다..pdf. 루프 내부에는 $f
처리된 .pdf 파일의 이름이 포함됩니다.
여기
int="$(basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1)"
우리는 사용명령 대체
주어진 파일 이름의 정수 부분을 변수에 할당합니다. 터미널에서 파이프라인에서 basename
수행되는 작업과 재생산 작업을 확인할 수 있습니다 .man basename
$ f='C Block Scan copy 1.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
1
$ f='C Block Scan copy 5.pdf'
$ echo basename "$f" | rev | cut -d ' ' -f1 | rev | cut -d . -f1
5
( $
여기에는명령줄 프롬프트
명령의 일부가 아닌 새 줄의 시작을 나타내는 데 사용됩니다.
다음 줄에서
name="$(basename "$f" | rev | cut -d ' ' -f2- | rev)"
.pdf의 이름 부분, 즉 숫자 앞의 모든 부분을 추출합니다.
다음 줄에서
padded_int="$(printf "%02d\n" "$int")"
Bash 내장 printf
명령을 사용하여 이를 패딩 $int
하고 이라는 변수에 저장합니다 padded_int
. 루프의 마지막 줄에서
echo mv "$f" "$(printf "%s %s.pdf" "$name" "$padded_int")"
echo
물론 실제 이름 바꾸기 printf
및 명령 대체를 다시 실행합니다 . C에서와 마찬가지로 printf
2개의 형식 지정자와 2개의 해당 인수와 함께 사용됩니다.%s
마지막 줄
done
루프를 닫습니다.
답변3
PE 매개변수 확장을 사용합니다. 셸 mv
의 외부 도구 에만 해당됩니다 bash
.
#!/usr/bin/env bash
shopt -s nullglob
for f in *[[:space:]][0-9].pdf; do
n=${f##* } ##: Remain only 1.pdf, 2.pdf etc.
n=0${n%.*} ##: Remain only 1 , 2 etc. and pad 0 so it will be 01, 02 ..
echo mv -v "$f" "${f/[0-9]/"$n"}" ##: Replace all [0-9] with the value of "$n"
done
- 보다매개변수 확장