정의된 디렉터리(예: /A/B)에 일부 .xls 파일이 있습니다. 처음 10개의 최신 파일 이름을 바꾸고 이름에 "-bkp"를 추가하고 싶습니다.
시도해봤는데 안되네요
ls -lt *.xls | head -1 | awk '{print "mv " $9 " "$9-bkp}' | sh
find 및 -exec를 시도했지만 최신 수정 파일 상위 10개를 어떻게 얻을 수 있나요?
답변1
매개변수로 -10
및 없이를 사용해야 하며 따옴표도 필요 하므로-1
head
-bkp
ls -lt *.xls | head -10 | awk '{print "mv " $9 " "$9"-bkp"}' | sh
작동해야합니다. 을 삭제하려고 하면 | sh
명령이 awk print 명령으로 끝나는 것을 알 수 있습니다.
답변2
파일 이름에 포함될 수 있는 문자에 대해 어떤 가정도 하지 않으려면 다음을 수행할 수 있습니다.
ls -dt ./*.xls | awk -v q="'" -v n=10 '
function process() {
if (NR > 1) {
gsub(q, q "\\" q q, file)
print "mv " q file q, q file "-bkp" q
if (!--n) exit
}
}
/\// {
process()
file = $0
next
}
{file = file "\n" $0}
END {process()}' | sh -x
또는 다음과 같은 경우 zsh
:
for f (*.xls(om[1,10])) cp -- $f $f-bkp
또는
autoload zmv
zmv -C '*.xls(#qom[1,10])' '$f-bkp'
답변3
ksh93(배열용) 및 Perl(타임스탬프/통계용)이 있는 경우 다음이 작동합니다.
files=(*.xls)
# exit early if there are no matching files
[ "$files" = "*.xls" ] && exit 0
for index in ${!files[@]}
do
t[$index]=$(perl -e '$x=(stat(shift))[9]; print "$x"' "${files[index]}")
done
for i in ${!t[@]}
do
printf "%d %d\n" ${t[i]} $i
done | sort -rn | head -10 | while read t i
do
mv "${files[i]}" "${files[i]}-bkp"
done
*.xls 파일 목록을 수집한 다음 해당 파일을 반복하고, perl
단일 라인 함수를 호출하여 각 파일의 마지막 수정된 타임스탬프를 인쇄하고, 결과를 병렬 배열에 저장하는 방식으로 작동합니다 t
.
그런 다음 t를 반복하고 타임스탬프와 배열 인덱스를 인쇄하고 sort
처음으로 파이프하여 가장 최근에 수정된 파일을 가져오고 head
처음 10개 파일로 파이프한 다음 해당 출력으로 다시 루프하여 mv
적절한 파일을 호출합니다.
답변4
ls에는 "시간" 값을 취하는 "정렬" 인수가 있습니다.
#!/bin/bash
IFS=$'\n'
for file in $(ls *.xls --sort=time|head -n 10);
do
mv $file $file-bkp
done
unset IFS
IFS 헛소리는 파일 이름에 공백이 있으면 for 루프가 무례해지기 때문입니다. 나는 이 문제에 대한 더 전통적인 해결책이 있다고 확신하지만 내 해결책은 효과가 있습니다. 파일 이름에 공백이 포함되어 있지 않다는 것을 알고 있는 경우 IFS가 포함된 줄을 삭제할 수 있습니다.