Bashスクリプトを使用してLinux環境で一時ファイルを管理するソリューションが必要です。
- ファイルがルートフォルダにあり、10日間変更されていないままになっている場合は、ファイルをサブフォルダに移動してタイムスタンププレフィックス(「2022-01-01_filename」など)を追加します。
- 以前に移動したファイルが変更された場合は、タイムスタンププレフィックスなしでルートフォルダに返す必要があります。
- 最後の変更日から90日以内に変更されていないファイルを削除します。
私が試したことは次のとおりです。いくつかのエラーが発生しましたが、そのエラーを修正した後は何も起こらないようです。とにかく、何時間も悩んだ最後に変更された日付で並べ替えることができるファイルマネージャを使用することをお勧めします。
#!/bin/bash
FOLDER="$HOME/tmp"
SUBFOLDER="$HOME/tmp/old"
[ ! -d "$FOLDER" ] && mkdir -p "$FOLDER"
[ ! -d "$SUBFOLDER" ] && mkdir -p "$SUBFOLDER"
find "$FOLDER" -maxdepth 1 -type f -mtime +10 -exec sh -c '
for file do
timestamp=$(date +"%Y-%m-%d")
new_filename="$SUBFOLDER/$timestamp_$(basename "$file")"
mv "$file" "$new_filename"
done' sh {} +
find "$SUBFOLDER" -type f -mtime -10 -exec sh -c '
for file do
new_filename="$FOLDER/${file#*_}"
mv "$file" "$new_filename"
done' sh {} +
find "$SUBFOLDER" -type f -mtime +90 -exec rm {} \;
chmod +x /path/to/script.sh
crontab -e
0 0 * * * /path/to/script.sh
答え1
このコードにはいくつかの問題があります(一部はマイナーな問題です)。
FOLDER
これらの変数と変数は環境にエクスポートされないため、SUBFOLDER
から始まる呼び出しでは使用できません。sh
find
- ディレクトリは
~/tmp
プライベートでなければなりませんmkdir -m 700 ~/tmp
。 - これは
[ -d ... ] || mkdir ...
典型的なTOCTOU競争モードです。事前検査は不要ですmkdir -p
。 $(...)
任意のファイル名で使用できないように末尾の改行を削除します。- エラー処理は行いません。エラーがある場合は、少なくとも終了ステータスを報告できます。
- 繰り返すたびに、今日の日付を計算する必要はありません。
- これは
-mtime +10
11日以上のファイルに適用され、-mtime -10
10日未満のファイルに適用されるため、24時間期間のファイル(10〜11日前に最後に変更されたファイル)はここでは扱いません。 find
2番目のコマンドは、名前に文字が含まれていないか含まれているファイルがある場合は、期待どおりに機能しません。たとえば、もしそうであれば、次のようになり、for、thenが与えられます。_
$SUBFOLDER
_
$file
/home/you/tmp/old/old-file
$new_file_name
/home/you/tmp//home/you/tmp/old/old-file
/home/your_home/tmp/old/2023-10-01_file
/home/your_home/tmp/home/tmp/old/2023-10-01_file
mv
すでに存在するターゲットファイル(ディレクトリまたはディレクトリへのシンボリックリンク)が処理されないなどの競合。-maxdepth
標準find
述語ではありません。
そしてzsh
:
#! /bin/zsh -
autoload zmv || exit
mkdir -pm 700 -- ~/tmp && cd -P -- ~/tmp && mkdir -p old || exit
today=${(%):-%D{%F}} ret=0
# move 10 day old or older regular files
zmv '*(#qND.m+9)' 'old/${today}_$f' || ret=$?
# move back regular files that are less than 10 day old.
zmv 'old/<1900-2100>-<1-12>-<1-31>_(*)(#qND.m-10)' '$1' || ret=$?
# remove regular files that are 91 day old or older
rm -f old/*(ND.m+90) || ret=$?
exit $ret
(sh
bashにはshよりも有用な拡張機能がないため、bashを使用する必要はありません。これはここで役に立ちます。自分のコードにbashに関連するものはなく、代わりに.sh
スクリプトに拡張機能を提供します.bash
。)
#! /bin/sh -
mkdir -pm 700 -- ~/tmp && cd -P -- ~/tmp && mkdir -p old || exit
TODAY=$(date +%Y-%m-%d) || exit
export TODAY
ret=0
# move 10 day old or older regular files
find . ! -name . -prune -type f -mtime +9 -exec sh -c '
ret=0
for file do
file=${file#./}
mv -i -- "$file" "old/${TODAY}_$file" || ret=$?
done
exit "$ret"' {} + || ret=$?
# move back regular files that are less than 10 day old.
LC_ALL=C find old/. ! -name . -prune \
-name '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_*' \
-type f -mtime -10 -exec sh -c '
ret=0
for file do
new=${file#*/./}
new=${new#*_}
if [ -d "$new" ]; then
printf>&2 "%s\n" "$new is a directory"
ret=1
else
mv -i -- "$file" "$new" || ret=$?
fi
done
exit "$ret"' {} + || ret=$?
# remove regular files that are 91 day old or older
find old/ -mtime +90 -type f -exec rm -f {} + || ret=$?
exit "$ret"
-i
競合を処理するためにここで使用されるオプションmv
。対話的に実行すると、ファイルを上書きするとメッセージが表示されます。cron
stdin isで実行すると上書きは/dev/null
拒否されますが、残念ながら失敗した場合は返されません。-n
GNUオプションも参照してくださいmv
(ただし失敗も返しません)。
ディレクトリ(またはディレクトリへのシンボリックリンク)として存在する場合、名前は変更されずに移動mv a b
されます。したがって、事前に確認してください。しかし、これはまたTOCTOU競争を導入します。 GNUの実装には便利なオプションがあります。の衝突処理において同様の競争条件があります。 GNUシステムに渡すと、これらの問題の少なくとも一部を軽減するのに役立ちます。a
b
b
b
[ -d
mv
-T
zsh
zmv
-o -nT
zmv
(注:私はコードをテストしていません。)