파일 이름의 날짜를 기준으로 오래된 백업을 삭제하는 방법은 무엇입니까?

파일 이름의 날짜를 기준으로 오래된 백업을 삭제하는 방법은 무엇입니까?

다음 이름의 일일 백업이 있습니다.

yyyymmddhhmm.zip // pattern
201503200100.zip // backup from 20. 3. 2015 1:00

3일이 지난 모든 백업을 삭제하는 스크립트를 생성하려고 합니다. 또한 스크립트는 패턴과 일치하지 않는 폴더의 다른 모든 파일을 삭제할 수 있어야 합니다(그러나 이를 비활성화하는 스위치가 스크립트에 있습니다).

파일 수명을 확인하기 위해 다른 프로그램도 파일을 조작하고 변조될 수 있으므로 백업 타임스탬프를 사용하고 싶지 않습니다.

의 도움으로:UNIX에서 5일보다 오래된 파일 삭제(타임스탬프가 아닌 파일 이름의 날짜) 나는 가지고있다:

#!/bin/bash

DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups/
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)

ls -1 ${BACKUPS_PATH}????????????.zip |
  while read A DATE B FILE
  do
     [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
  done

if [ $DELETE_OTHERS == "yes" ]; then
    rm ${BACKUPS_PATH}*.* // but I don't know how to not-delete the files matching pattern
fi

하지만 계속해서 이렇게 말합니다.

rm: missing operand

문제는 무엇이며 스크립트를 완성하는 방법은 무엇입니까?

답변1

코드의 첫 번째 문제는 다음과 같습니다.분석하다ls. 즉, 파일이나 디렉터리 이름에 공백이 있으면 쉽게 손상될 수 있습니다. 쉘 와일드카드를 사용하거나 대신 사용해야 합니다 find.

더 큰 문제는 데이터를 올바르게 읽지 않는다는 것입니다. 귀하의 코드:

ls -1 | while read A DATE B FILE

결코 채워지지 않습니다 $FILE. 의 출력은 ls -1단지 파일 이름 목록이므로 해당 파일 이름에 공백이 포함되어 있지 않으면 read지정한 4개 변수 중 첫 번째 변수만 채워집니다.

다음은 스크립트의 작업 버전입니다.

#!/usr/bin/env bash

DELETE_OTHERS=yes
BACKUPS_PATH=/mnt/\!ARCHIVE/\!backups
THRESHOLD=$(date -d "3 days ago" +%Y%m%d%H%M)

## Find all files in $BACKUPS_PATH. The -type f means only files
## and the -maxdepth 1 ensures that any files in subdirectories are
## not included. Combined with -print0 (separate file names with \0),
## IFS= (don't break on whitespace), "-d ''" (records end on '\0') , it can
## deal with all file names.
find ${BACKUPS_PATH} -maxdepth 1 -type f -print0  | while IFS= read -d '' -r file
do
    ## Does this file name match the pattern (13 digits, then .zip)?
    if [[ "$(basename "$file")" =~ ^[0-9]{12}.zip$ ]]
    then
        ## Delete the file if it's older than the $THR
        [ "$(basename "$file" .zip)" -le "$THRESHOLD" ] && rm -v -- "$file"
    else
        ## If the file does not match the pattern, delete if 
        ## DELETE_OTHERS is set to "yes"
        [ $DELETE_OTHERS == "yes" ] && rm -v -- "$file"
    fi
done

답변2

FreeBSD에서 사용됨: 예: /usr/home/foobar에서 5760분(4일)보다 오래 된 foobar 소유의 모든 파일을 찾아 삭제합니다.

find /usr/home/foobar -user foobar -type f -mmin +5760 -delete

답변3

sed과 사이의 줄을 잊지 마세요 . 이 줄이 중요합니다.ls -1while read

내가 제안하고 싶은 첫 번째 질문은 다음과 같습니다. (awk 교체에 상응하는 sed를 찾을 수 없습니다.)

ls -1 ${BACKUPS_PATH}????????????.zip |\
  awk -F. '{printf "%s %s\n",$1,$0 ;}' |\
  while read DATE FILE
  do
     [[ $DATE -le $THRESHOLD ]] && rm -v $BACKUPS_PATH$FILE
  done

제공된 쉘 연산은 테스트용으로 최소 37비트입니다 $DATE -le $THRESHOLD.

관련 정보