~/folder/ contain (최신 파일부터 가장 오래된 파일까지)와 같은 디렉토리에 있는 모든 파일의 이름을 바꾸려고 합니다: apple.foo, Pie.foo, cookie.foo, melon.foo
고정 접두사와 숫자 001을 사용하여 이름을 바꿉니다.가장 오래된999로 증가합니다.
melon.foo >> object001.foo
쿠키.foo >> object002.foo
파이.foo >> object003.foo
apple.foo >> object004.foo
누구든지 이것을 달성하는 방법을 알고 있습니까?
답변1
zsh
쉘 사용 :
counter=0
for name in $HOME/folder/*(.NDOm); do
counter=$(( counter + 1 ))
suffix=$name:e
printf -v newname '%s/object%.3d%s' $name:h $counter ${suffix:+.$suffix}
mv $name $newname
done
~/folder
이는 마지막으로 수정된 타임스탬프를 기준으로 가장 오래된 것부터 최신 것까지 디렉터리에 있는 일반 파일의 모든 이름을 반복합니다 . 각 이름에 대해 현재 이름의 디렉터리 부분과 카운터를 사용하여 새 이름을 구성합니다. 파일 이름이 새 이름으로 변경됩니다(확인 필요 없음, 이름 충돌 확인 없음).
이 printf -v newname
호출은 출력을 변수로 "인쇄"합니다 newname
. 형식 문자열은 세 위치 (예: 등) 에 %.3d
0으로 채워진 정수를 출력합니다. 001
매개변수 확장은 경로 이름의 헤더/디렉토리 부분으로 확장됩니다(동일).023
109
$name:h
$name
dirname "$name"
원래 파일 이름(즉 , 현재 파일이 )으로 확장 될 $name:e
"확장자" 는 에 저장됩니다 . 파일 확장자가 있으면 앞에 점을 추가합니다.foo
apple.foo
suffix
${suffix:+.$suffix}
파일 이름 와일드카드 패턴 끝에 있는 in은 이전 와일드카드 패턴이 일반 파일에만 일치하도록 하는 와일드카드 문자입니다 .
. 패턴이 마치 쉘에 설정된 것처럼 동작하도록 합니다 (.NDOm)
( 일치하는 항목이 없으면 아무것도 확장하지 않고 결과에 숨겨진 이름을 포함합니다). 가장 오래된(가장 최근에 수정된) 파일이 먼저 정렬되도록 일치하는 이름을 정렬합니다.N
D
nullglob
dotglob
bash
Om
로그인 셸이 아닌 경우 zsh
스크립트로 실행할 수 있습니다.
$ zsh ./this-script
답변2
bash
이것은 구문 분석이 필요하지 ls
않고 법적으로 명명된 모든 파일(삽입 공백, 구두점, 개행 문자 등)을 처리할 수 있는 GNU 유틸리티로 작성된 버전입니다.
#!/bin/bash
k=0 # start at the beginning
find *.foo -type f -printf "%T@ %p\0" | # list all the files with modification time
sort -z | # sort by increasing modification time
cut -z -d' ' -f2- | # discard the time value leaving just the name
while IFS= read -r -d '' file # now loop for each file...
do
((++k)) # next count
seq=$(printf "%03d" $k) # format the three-digit counter
name="${file%.*}" ext="${file##*.}" # split filename into name and extension
echo will mv "$file" "$name.$seq.$ext" # show what would happen without doing it
done
echo will
mv
명령을 실행할 준비가 되면 삭제하십시오.
예
# preparation
for f in {melon,cookie,pie,apple}.foo; do touch "$f"; sleep 1; done
# list in order of modification time (oldest to newest)
ls -tr
melon.foo cookie.foo pie.foo apple.foo
# run the script and observe the output
k=0; find *.foo -type f -printf "%T@ %p\0" | sort -z | cut -z -d' ' -f2- | while IFS= read -r -d '' file; do ((++k)); seq=$(printf "%03d" $k); name="${file%.*}" ext="${file##*.}"; echo mv "$file" "$name.$seq.$ext"; done
will mv melon.foo melon.001.foo
will mv cookie.foo cookie.002.foo
will mv pie.foo pie.003.foo
will mv apple.foo apple.004.foo
답변3
파일 이름에 공백, 탭 또는 줄 바꿈이 포함되어 있지 않다고 가정하면 한 줄 bash
및 다음을 사용하는 것이 awk
쉽습니다 .
ls -rt | awk -F "." '{print $0 " object" sprintf("%03d",NR) "." $NF }' | xargs -L 1 mv
이 명령은 각 라인에 대해 실행됩니다 xargs -l
. mv
명령을 실행하기 전에 다음 명령을 실행하여 대상 파일 이름과 소스 파일 이름이 올바른지 확인하십시오.
ls -rt | awk -F "." '{print $0 " object" sprintf("%03d",NR) "." $NF }'
출력은 다음과 유사해야 합니다.
melon.foo object001.foo
cookie.foo object002.foo
pie.foo object003.foo
apple.foo object004.foo