
「/media/downloads/」と「/home/uploads/」という2つのフォルダがあります。 「/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の代わりにまたは使用するのは簡単です(またはに変更することはできますが、テストしていないので確かに言うことはできません)。違いがあるかもしれません。zsh
ksh
bash -c
ksh -c
zsh -c
¹計算方法の詳細を調べてman find
検索してください。あなた自身にもっと適しているかもしれません。興味があれば、探すオプションも可能です。-atime
-mtime 14
-daystart