다음 이름의 일일 백업이 있습니다.
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 -1
while 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
.