Bash 스크립트: 최신 복사본을 유지하면서 오래된 파일을 조건부로 삭제합니다.

Bash 스크립트: 최신 복사본을 유지하면서 오래된 파일을 조건부로 삭제합니다.

참고: jeff-schaller의 답변이 있지만 zsh; 그래서 나는 을 기반으로 답변을 얻고 싶습니다 Bash.

나는 백업 디렉터리에서 오래된 파일을 조건부로 삭제하는 Bash 스크립트를 만드는 것을 좋아합니다.

2개의 개별 파일 백업에는 2가지 조건이 있습니다.

1, 의 최신 복사본을 유지 Edge_Profile_*.tgz하고 나머지는 삭제합니다.Edge_Profile_*.tgz 5일이 넘은 경우에만.

2, 의 최신 복사본을 유지 Firefox_Profile_*.tgz하고 나머지는 삭제합니다 Firefox_Profile_*.tgz.그 사람들이 몇 살인지는 상관없어.

이 AskUbuntu 답변을 수정하는 방법은 다음과 같습니다.https://askubuntu.com/a/933098/928088

스크립트:

#!/bin/bash

LOG_FILE="/home/admn/Cleanup.log"
TEMP_LOG="/tmp/Temp_Cleanup.log"

mv $LOG_FILE $TEMP_LOG

{

cd /home/admn/Downloads/Test;

echo "Cleanup log:" `date`

find /home/admn/Downloads/Test/Edge_Profile_*.tgz -type f \( -mtime +5 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac;
done

echo

find /home/admn/Downloads/Test/Firefox_Profile_*.tgz -type f \( -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
    sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
        case "$flag" in 
            'Y') echo rm "$file" 
               ;; 
            *) echo "skipping $file (too new)"
               ;; 
        esac        
done

} &>> $LOG_FILE

cat $TEMP_LOG >>$LOG_FILE

exit;

다음을 사용하여 로그 파일에 출력합니다 echo.

/usr/local/scripts/cleanup.sh

rm /home/admn/Downloads/Test/Edge_Profile_Jul_06_2021_00-35.tgz
rm /home/admn/Downloads/Test/Edge_Profile_Jul_07_2021_00-35.tgz
....
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new)
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new)
....

rm /home/admn/Downloads/Test/Firefox_Profile_Jul_01_2021_00-35.tgz
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_02_2021_00-35.tgz
....

다음 을 제외하고 실제로 스크립트를 실행하는 동안 로그 파일에 출력됩니다 echo.

/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new): No such file or directory
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new): No such file or directory
....

디렉터리의 총 파일: 20개 파일

1, Edge_Profile_*.tgz: 7월 6일부터 7월 17일까지: 12개 파일

2, Firefox_Profile_*.tgz: 7월 1일부터 7월 8일까지: 8개 파일

문제:

(1) 나생각하다스크립트는 작동하고 있지만 무슨 일이 일어나고 있는지 알지 못한 채 대부분의 부분을 수정했기 때문에 잘 모르겠습니다.

(2) 로그 파일로 출력:

echo다음과 같이 파일 이름(전체 경로가 아님)만 제외하고 로 얻은 로그 파일에서 정확히 동일한 출력을 선호합니다.

rm Edge_Profile_Jul_11_2021_00-35.tgz

skipping Edge_Profile_Jul_12_2021_00-35.tgz (too new)

운영 체제: 우분투 MATE 21.04

정말 감사합니다.

답변1

파일에 직접 액세스할 수 있는 셸에서는 수정 시간을 기준으로 파일을 조작하는 것이 훨씬 쉽습니다. zsh는 그러한 쉘 중 하나입니다. 간단히 sudo apt install zsh설치하면 됩니다. 파일이 하나의 디렉터리에 있는 것으로 나타나므로 이 답변은 비재귀적입니다. 더 간단한 사례를 먼저 시연해 보겠습니다.

  • Firefox_Profile_*.tgz의 최신 복사본을 유지하고 오래된 파일의 나머지 부분을 삭제하려면:

    echo would rm -v -- Firefox_Profile_*.tgz(.om[2,-1])
    

    제거echo would올바른 것처럼 보이면 해당 부분을 . 이것은glob(와일드카드) 한정자괄호 안에는 세 가지 작업을 수행합니다.

    • 일반 파일(디렉토리나 소켓 등이 아닌)만 선택합니다..
    • 수정 시간을 기준으로 최신순으로 파일을 정렬(정렬)합니다.om
    • 두 번째 요소부터 끝까지 결과 목록의 조각을 선택합니다. 첫 번째(최신) 파일을 건너뜁니다.[2,-1]

    일치하는 파일이 없으면 zsh는 중지하고 "zsh: 일치하는 항목을 찾을 수 없습니다"라는 메시지를 표시하며 rm.

  • Edge_Profile_*.tgz의 최신 복사본을 유지하고 5일이 지난 경우에만 나머지 복사본을 삭제하려면 먼저 최신 복사본을 가져옵니다.

    newest=(Edge_Profile_*.tgz(.om[1]))
    

    ... 그런 다음 5일보다 오래된 항목을 얻습니다.

    older=(Edge_Profile_*.tgz(.m+5))
    

    여기서 새로운 부분은 수정자 +5에 있습니다 m. 그러면 5일보다 오래된 파일이 선택됩니다. 그런 다음 제거할 목록에 최신 항목이 없는지 확인합니다.

    remove=("${(@)older:|newest}")
    

    여기서 새로운 부분은 배열 빼기 기호입니다 :|. 그것은에 문서화되어 있습니다zsh 매뉴얼의 매개변수 확장 섹션. "최신"이 아닌 "이전" 요소를 선택합니다. 마지막으로 해당 파일 목록을 제거합니다.

    echo would rm -v -- "${remove[@]}"
    

관련 정보