유닉스에서 60개 이상의 파일이 있는 폴더의 파일을 삭제하는 방법은 무엇입니까?

유닉스에서 60개 이상의 파일이 있는 폴더의 파일을 삭제하는 방법은 무엇입니까?

특정 시간에 실행될 cronjob에 스크립트를 배치하고 파일 수가 60개를 초과하면 폴더에서 가장 오래된 파일을 삭제하고 싶습니다. 후입 선출법. 열심히 노력했는데,

#!/bin/ksh  
for dir in /home/DABA_BACKUP  
do  
    cd $dir  
    count_files=`ls -lrt | wc -l`   
    if [ $count_files -gt 60 ];  
    then  
        todelete=$(($count_files-60))  
        for part in `ls -1rt`  
        do  
            if [ $todelete -gt 0 ]  
            then  
                rm -rf $part  
                todelete=$(($todelete-1))  
            fi  
        done  
    fi
done   

매일 저장되고 이름이 지정되는 백업 파일입니다 backup_$date. 이거 괜찮아?

답변1

아니요, 우선 줄 바꿈이 포함된 파일 이름이 손상됩니다. 또한 필요 이상으로 복잡하고 다음과 같은 모든 위험을 안고 있습니다.ls를 구문 분석하다.

더 나은 버전은 다음과 같습니다(GNU 도구 사용).

#!/bin/ksh  
for dir in /home/DABA_BACKUP/*
do
    ## Get the file names and sort them by their
    ## modification time
    files=( "$dir"/* );
    ## Are there more than 60?
    extras=$(( ${#files[@]} - 60 ))
    if [ "$extras" -gt 0 ]
    then
    ## If there are more than 60, remove the first
    ## files until only 60 are left. We use ls to sort
    ## by modification date and get the inodes only and
    ## pass the inodes to GNU find which deletes them
    find dir1/ -maxdepth 1 \( -inum 0 $(\ls -1iqtr dir1/ | grep -o '^ *[0-9]*' | 
        head -n "$extras" | sed 's/^/-o -inum /;' ) \) -delete
    fi
done

이는 모든 파일이 동일한 파일 시스템에 있다고 가정합니다. 그렇지 않으면 예기치 않은 결과(예: 잘못된 파일 삭제)가 발생할 수 있습니다. 동일한 inode를 가리키는 하드 링크가 여러 개 있는 경우에도 제대로 작동하지 않습니다.

답변2

#! /bin/zsh -
for dir (/home/DABA_BACKUP/*) rm -f $dir/*(Nom[61,-1])

~을 위한zsh-무지;-):

  • for var (list) cmd: 루프의 짧은 버전입니다 for var in list; do cmd; done(구문을 연상시킵니다 perl).
  • $dir: zsh다른 쉘처럼 변수를 zsh인용할 필요가 없습니다.분명히 split연산자 이므로 glob암시적으로 수행하지 마세요.분할+전역매개변수가 확장된 경우.
  • *(...): 그리고글로벌 예선:
  • N: nullglob: 불일치가 있으면 오류를 발생시키는 대신 glob이 null로 확장됩니다.
  • m:생성된 파일을 다음 위치에 배치합니다.수정 시간(가장 작은 것부터).
  • [61,-1]: 정렬된 목록의 하단에서 61번째 항목을 선택합니다.

따라서 기본적으로 60개의 가장 어린 파일을 제외한 모든 파일이 삭제됩니다.

답변3

제거할 가장 오래된 항목 목록을 얻으려면(최신 항목 60개 유지):

ls -t | tail -n +61

접근 방식의 주요 문제는 여전히 여기에서 해결해야 합니다. 만약을 대비하여 파일을 처리하는 방법(다소 복잡한 프로그램을 대체):

cd /home/DABA_BACKUP || exit 1
ls -t | tail -n +61 | xargs rm -rf


참고: 당신이 가지고 있는 것처럼 보이기 때문에일일 백업find예를 들어, 파일 날짜의 합계를 기반으로 하는 방법을 사용할 수도 있습니다 .

find /home/DABA_BACKUP -mtime +60 -exec ls {} +

( ls이 명령은 올바른 작동을 다시 확인한 후 적절한 명령으로 대체됩니다 rm.)

답변4

파일 이름이 모두 backup_*이라는 것을 알고 있는 경우 해당 파일만 처리하고 실수로 디렉토리에 들어간 파일은 처리하지 않도록 해당 파일을 ls 명령에 포함해야 합니다. 그런 다음 파이프라인에서 ls를 사용하여 한 줄에 1개의 파일만 나열한 다음 개수만 계산하므로 정렬이 필요하지 않습니다.

count_files=$(ls -U backup_* | wc -l)

그리고

for part in $(ls -rt backup_*);do
    rm -rf "$part"
    todelete=$(($todelete-1))
    if [[ $todelete -eq 0 ]]; then
        break
    fi
done

관련 정보