"/media/downloads/" 및 "/home/uploads/"라는 두 개의 폴더가 있습니다. "/home/uploads/"에 있는 경우 "/media/downloads/"에서 15년 된 파일을 삭제하고 싶습니다.
이를 수행하는 가장 좋은 스크립트는 무엇입니까?
미리 감사드립니다.
답변1
그리고 zsh
:
cd /home/uploads
uploaded_files=( **/*(ND.) )
cd /media/downloads
old_downloads=( **/*(ND.m+14) )
echo rm -- ${old_downloads:*uploaded_files}
( echo
실제로 파일을 삭제하려면 삭제하세요.)
/media/downloads
동일한 경로에 일반 파일이 존재하는 경우 /home/uploads
동일한 내용을 가지고 있는지 확인하지 않습니다.
스크립트로 보면 다음과 같습니다.
#! /bin/zsh -
die() {
print -ru2 -C1 -- "$@"
exit 1
}
usage() {
die "$@" "Usage: $ZSH_SCRIPT:t [-d <days>] [-n] <srcdir> <dstdir>" \
'' \
' Removes files from <srcdir> if their age rounded down to an' \
' integer number of days is strictly greater than <days> (14 by' \
' default). -n for dry-run'
exit 1
}
zmodload zsh/system || die
dryrun=0 days=14
while getopts nd: o; do
case $o in
(n) dryrun=1;;
(d) days=$OPTARG;;
(*) usage;;
esac
done
shift OPTIND-1
(( $# == 2 )) || usage
[[ $days = <0-> ]] || usage "$days is not a positive decimal integer"
src=$1 dst=$2
[[ -d $src ]] || die "$src is not a directory"
[[ -d $dst ]] || die "$dst is not a directory"
list() {
local dir=$1 var=$2 qual=$3 err
ERRNO=0
() { eval $var'=( "${@#$dir/}" )'; } $dir/**/*(ND.$qual)
if (( ERRNO )); then
syserror -e err
die "An error was encountered during $dir traversal: $err"
fi
}
list $src old_in_src m+$days
list $dst all_in_dst oN
to_remove=( ${old_in_src:*all_in_dst} )
if (( dryrun )); then
if (( $#to_remove )); then
print -ru2 -C1 "$#old_in_src old files found in $src, out of which $#to_remove are also found in $dst:" ' - '$^to_remove
else
print -ru2 "No file found to remove ($#old_in_src old files in $src in total)"
fi
else
rm -f -- $src/$^to_remove
fi
답변2
사용 find
및 bash
:
find /media/downloads/ -type f -mtime +15 \
-exec bash -c 'for f; do
f2=${f/"/media/downloads/"/}
test -e "/home/uploads/$f2" && delfiles+=("$f");
done;
[ -n "$delfiles" ] && printf "rm %q\n" -- "${delfiles[@]}"' bash {} +
find
15일보다 오래된 모든 일반 파일을 찾아 에 인수로 전달합니다 bash
. 각 파일 이름에 대해 bash는 파일 이름에서 최상위 디렉터리( /media/downloads/
)를 제거한 다음 에 있는 나머지 파일 이름(있는 경우 하위 디렉터리 포함)을 확인합니다 /home/uploads/
. 따라서 파일은 이름이 지정된 배열에 추가됩니다 $delfiles
.
모든 파일 이름 매개변수를 반복한 후에는 배열의 각 파일 이름을 인쇄합니다.
이것은 시험 실행으로 작성되었으므로전시하다실제로 그렇게 하지 않았다면 어떻게 될까요? 실제로 파일을 삭제하려면 printf "rm %q\n" --
다음으로 변경하십시오.rm --
삭제된 후 내용이 비어 있더라도 디렉터리는 절대 삭제되지 않습니다. 이 작업을 수행해야 하는 경우 파일을 삭제한 후 다음 명령(GNU find 사용)을 실행할 수 있습니다.
find /media/downloads/ -mindepth 1 -type d -empty -delete
또한 주목할 가치가 있습니다: 둘 다 zsh
유사한 매개변수 확장 및 문자열 수정 기능을 가지고 있으므로 ksh
bash 대신 또는 사용하기가 간단해야 합니다(또는로 변경할 수도 있지만 테스트하지 않았으므로 확실히 말할 수는 없습니다. bash 및 껍질마다 약간의 차이가 있을 수 있습니다.zsh
ksh
bash -c
ksh -c
zsh -c
¹계산 방법에 대한 자세한 내용을 살펴보고 man find
검색해 보세요. 자신에게 더 적합할 수도 있습니다. 관심이 있다면 찾는 옵션도 가능합니다.-atime
-mtime 14
-daystart