폴더의 마지막(가장 최근) 20개 파일을 제외하고 모두 삭제[중복]

폴더의 마지막(가장 최근) 20개 파일을 제외하고 모두 삭제[중복]

다른 디렉터리의 모든 파일을 삭제하고 최신 20개 파일만 유지하고 싶습니다. 이 작업을 수행하는 올바른 명령입니까?

ls -t1 /mnt/dwh/ftp/dwh_ftp_cbs/ARLOGS/ | tail -n +22 | xargs rm -f

답변1

그리고 zsh그리고글로벌 예선:

print -rl -- *(D.Om[1,-21])

마지막(가장 최근에 수정된) 20개 파일을 제외한 모든 일반 파일이 나열됩니다.
D숨김 파일 선택, .일반 파일만 선택, Om역순 정렬을 의미합니다.시간(오래된 것부터) 그리고 [1,-21]마지막부터 처음부터 21일까지 선택하세요.
결과가 만족스러우면 다음 print -rl으로 바꾸세요 rm.

rm -- *(D.Om[1,-21])

파일 수가 많으면 사용을 zargs피해야 할 수도 있습니다.매개변수 목록이 너무 깁니다.:

autoload zargs
zargs ./*(D.Om[1,-21]) -- rm

답변2

ls교리문답인 출력 처리 등 명령에 많은 단점이 있습니다 . 바라보다이 기사왜 이렇게하지 않습니까?

이 방법은아니요GNU 확장이며 bash, zsh, ksh93, dash 및 ash에서 테스트되었습니다.

for f in * .*; do 
  [ -f "$f" ] && printf "%s " $(perl -e 'print((stat("$ARGV[0]"))[9])' -- "$f") && \
  printf "%s\0" "$f";
done | tr '\0\n' '\n\0' | sort -k1nr | \
sed "1,20d;s/'/'\"'\"'/g;s/[^ ]* \(.*\)/rm -f -- '\1';/" | tr '\0' '\n' | sh

이것은 내가 생성할 수 있었던 가장 이상한 파일 이름이며 심지어 작동합니다.

touch -- '--a'"'"'b"c
d$e\nf\r!g;h^i`j(k)l*m%n=o?p.txt'

또는 파일 이름에서 "점프 아웃"해 보십시오.

touch '\'"'"'echo test '"'"'\'

답변3

ls -t1 /mnt/dwh/ftp/dwh_ftp_cbs/ARLOGS/ | tail -n +22 | xargs rm -f

의 출력에는 ls전체 경로가 아닌 파일 이름만 포함되므로 작동하지 않습니다. 또한 로 시작하는 이름도 건너뜁니다 ..

cd /mnt/dwh/ftp/dwh && ls -At1 | tail -n +21 | xargs rm -f --

이 문제는 해결될 수 있지만 공백, 개행, 아포스트로피, 백슬래시 또는 큰따옴표 문자가 포함된 파일 이름에는 여전히 문제가 있습니다(그리고 파일 이름에는 로케일에서 유효한 문자를 형성하지 않는 바이트가 포함될 수 있습니다).

(export LC_ALL=C
 cd /mnt/dwh/ftp/dwh && ls -At1 |
   tail -n +21 |
   sed 's/"/\\"/g;s/.*/"&"/' |
   xargs rm -f --
)

이렇게 하면 대부분의 문제가 해결되지만 개행 문자가 포함된 파일 이름에는 여전히 문제가 있습니다. 문제는 출력을 ls -At1사후 처리할 수 없다는 것입니다.

의 출력은 ls -Atd1 ./.* ./*후처리될 수 있습니다(이 ./접두사는 출력에서 ​​각 파일 이름이 시작되는 위치를 나타내기 때문에 쉽지는 않지만). 파일 이름 목록을 전달하면 명령에 전달되는 인수 수 제한에 도달할 위험이 있습니다 ls.

가장 좋은 방법은전역 정렬이 가능한 쉘을 사용하세요., 또는 GNU 시스템에서만 작업해야 하는 경우 GNU 확장을 사용하세요.

 cd /mnt/dwh/ftp/dwh &&
   find . ! -name . -prune ! -type d -printf '%T@\t%p\0' |
     tr '\0\n' '\n\0' |
     sort -rn |
     tail -n +21 |
     cut -f 2- |
     tr '\0\n' '\n\0' |
     xargs -r0 rm -f

여기서는 파일 형식을 제외합니다.목차, 이는 번호 매기기에 영향을 주지만 디렉토리를 삭제하고 싶지 않을 것이라고 생각하기 때문에 아마도 원하는 것에 더 가깝습니다. 디렉토리를 제거하려면 해당 -type d옵션을 삭제하고 .-rrm

또는:

eval "set -- $(COLUMNS=4294967295 ls -Atx --quoting-style=shell-always)"
if [ "$#" -gt 20 ]; then
  shift 20
  printf '%s\0' "$@" | xargs -r0 rm -f --
fi

perl또는 , python, ruby... 와 같은 범용 프로그래밍 언어를 사용하십시오.

관련 정보