특정 수의 파일이 남을 때까지 파일을 삭제하기 위해 while 루프를 사용할 수 없습니다.
이것이 내가 가진 것입니다:
touch while/151234
touch while/152355
touch while/151694
touch while/153699
touch while/156946
NUMSNAPS=$(ls while | awk '{print $1}' | wc -l)
RETAIN=2
while [ "$RETAIN" -le "$NUMSNAPS" ]; do
OLDEST=$(ls | awk '{print $1}' | head -n 1)
rm "$OLDEST"
done
실제로 다른 타사 명령과 함께 사용되는 테스트이기 때문에 find를 사용하여 이러한 파일을 삭제할 수 없습니다. DOCTL을 사용하여 스냅샷을 찾고 하나가 남을 때까지 삭제할 계획입니다.
답변1
절대 변경하지 않는 두 개의 변수를 기반으로 특정 조건을 테스트하는 루프가 있습니다. NUMSNAPS
각 반복마다 값을 1씩 감소시키는 것을 의미한다고 가정합니다 .
zsh
쉘 에서는 할 수 있습니다
retain=2
rm -f while/*(DN.Om[retain+1,-1])
$retain
최근 수정된 파일을 제외한 모든 일반 파일(숨겨진 이름이 있는 파일 포함)을 삭제합니다 . 수천 개의 파일이 발생하는 경우 다음을 사용할 수 있습니다 zargs
.
retain=2
autoload -U zargs
zargs -- while/*(DN.Om[retain+1,-1]) -- rm
파일을 이름별로 정렬하려면 Om
("Mtime 타임스탬프 기준 내림차순 정렬")을 On
("이름별 내림차순 정렬")로 바꾸세요.
zsh
분명히 예를 들어 사용하는 대신 다른 쉘에서 호출할 수 있습니다 .
retain=2
zsh -c 'rm -f $2/*(DN.Om[$1+1,-1])' zsh "$retain" "while"
이는 또한 인라인 스크립트에 보관할 디렉터리 이름과 파일 수를 전달하므로 기존 비스크립트에 더 쉽게 병합할 수 있습니다 zsh
.
쉘 에서는 bash
실제로 원하지 않습니다출력 구문 분석ls
. 대신에 다음을 사용하고 싶을 수도 있습니다.
shopt -s dotglob nullglob
retain=2
set -- while/*
while [ "$#" -gt "$retain" ]; do
rm -f "$1"
shift
done
이는 위치 인수 목록을 while
디렉터리의 파일 목록(숨겨진 이름 포함)으로 설정한 다음 retain
목록에 파일만 남을 때까지 해당 목록에서 파일을 제거합니다.
이렇게 하면 어색한 파일 이름 문제를 방지하고 ls
삭제된 파일마다 한 번 호출하는 것을 방지할 수 있습니다.
이 코드는 이름(마지막으로 수정된 타임스탬프 아님)을 기준으로 파일을 삭제합니다. 이것은 귀하의 코드에서도 수행하려는 작업인 것 같습니다.
답변2
그런데 왜 전체 목록을 얻을 수 없고 필요한 파일 수만 유지할 수 없습니까? 예를 들어:
ls -r while | tail -n +${retain} | xargs echo rm
답변3
스크립트를 수정하고 개선하는 방법은 다음과 같습니다.
#!/bin/bash
touch while/151234
touch while/152355
touch while/151694
touch while/153699
touch while/156946
NUMSNAPS=$(ls -1 while | wc -l)
RETAIN=2
while (( RETAIN < NUMSNAPS )); do
OLDEST=$(ls -1t while | tail -n 1)
rm "while/$OLDEST"
(( --NUMSNAPS ))
done