特定のディレクトリのすべてのログファイルを削除したいのですが、最新のログファイルは削除したくありません。 3.
私はそれを完了しました:
DATA_PATH=$(gadmin config get System.DataRoot)
ZK_PATH=${DATA_PATH}/zk/version-2
log_count=$(ls -ltrh ${ZK_PATH} | grep log | wc -l)
limit_files=`expr $log_count - 3`
echo There is ${log_count} files found in ${ZK_PATH}, ${limit_files} will be deleted, here the list:
ls -ltrh ${ZK_PATH} | grep log | head -${limit_files}
while true; do
read -p "Are you sure to delete these files? " yn
case $yn in
[Yy1]* ) echo execute to delete the files; break;;
[Nn0]* ) exit;;
* ) echo "Please answer y or n.";;
esac
done
リストされている12個のファイルのうち9個をどのように削除しますか?
まず、リストをファイルに印刷してからループを使用して1つずつ削除することを検討しましたが、1行でこれを実行できるコードがあると確信しています。
find ... -delete
、-exec
と を使ってみましたxargs rm
が、正しく認識されませんでした。
どうすればいいですか?
答え1
この種の操作は、bashの代わりにzshを使用してより簡単で信頼性の高い作業を行うことができます。
#! /bin/zsh -
data_path=$(gadmin config get System.DataRoot) || exit
zk_path=$data_path/zk/version-2
keep=3
files=( $zk_path/*log*(N.om) )
if (( $#files > keep )); then
printf >&2 '%s\n' "$#files files found in $zk_path, $(( $#files - keep )) will be deleted, here is the list from newest to oldest:"
shift keep files
printf >&2 ' - "%s"\n' $files:t
read -q '?OK to delete? ' && rm -f -- $files
fi
特に興味深い点は$zk_path/*log*(N.om)
全体的な状況*log*
;パターンに一致するすべてのファイル名に展開され、角かっこはファイルが見つからない$zk_path
場合(…)
はエラーがないことを指定します(ullglob)。ディレクトリ、シンボリックリンク、デバイス...()N
ではなく、通常のファイルのみを探します。私たちはファイルを年齢の昇順でソート.
したいと思います(このように修正時間に基づいて)。o
m
ls -t
答え2
同様の状況で、私は次のアプローチを使用しました。 (おそらくこれは最も強力な解決策ではありませんが、一般的な状況ではまだ役に立つかもしれません...)
LOGDIR=my/logs ##
ls -dpt -- "$LOGDIR"/log* | # get log files sorted by date
grep -v '/$' | # but remove directories/ from the list
tail -n +4 | # remove also the newest 3
vidir -
でvidir
同意した場合は、すべての行を削除(例:dG
vimコマンドを使用)し、終了するとその行が削除されます。
vidir
fromはmoreutils
ディレクトリ用の投影エディタです(ディレクトリの内容の表示、名前の変更、削除に最適なツール)。
答え3
これにより、最新のファイルを除くすべてのファイルのリストが表示され、limit_files
後で削除できます。
FileList=`ls -1rt ${ZK_PATH}/*log* | head -${limit_files}`
rm $FileList
スペースやその他の特殊文字を含むファイルでは機能しませんが、私のログディレクトリのログファイルには英数字、ダッシュ、ピリオドのみが含まれているため、これはうまく機能します。