注意:雖然 jeff-schaller 給了答案,但它取決於zsh
;所以我想得到一個基於的答案Bash
。
我喜歡建立一個 Bash 腳本來有條件地從備份目錄中刪除舊檔案。
2 個不同的檔案備份有 2 個條件:
1、保留最新的副本Edge_Profile_*.tgz
,刪除其餘的Edge_Profile_*.tgz
僅當年齡超過 5 天時。
2, 保留最新的副本Firefox_Profile_*.tgz
,並刪除其餘的Firefox_Profile_*.tgz
,他們多大並不重要。
以下是我修改 AskUbuntu 答案的方法:https://askubuntu.com/a/933098/928088
腳本:
#!/bin/bash
LOG_FILE="/home/admn/Cleanup.log"
TEMP_LOG="/tmp/Temp_Cleanup.log"
mv $LOG_FILE $TEMP_LOG
{
cd /home/admn/Downloads/Test;
echo "Cleanup log:" `date`
find /home/admn/Downloads/Test/Edge_Profile_*.tgz -type f \( -mtime +5 -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
case "$flag" in
'Y') echo rm "$file"
;;
*) echo "skipping $file (too new)"
;;
esac;
done
echo
find /home/admn/Downloads/Test/Firefox_Profile_*.tgz -type f \( -printf 'Y\t' -o -printf 'N\t' \) -printf '%A@\t%p\0' |
sort -zk2,2 | head -zn -1 | while read -r -d '' flag _ file; do \
case "$flag" in
'Y') echo rm "$file"
;;
*) echo "skipping $file (too new)"
;;
esac
done
} &>> $LOG_FILE
cat $TEMP_LOG >>$LOG_FILE
exit;
在日誌檔案中輸出echo
:
/usr/local/scripts/cleanup.sh
rm /home/admn/Downloads/Test/Edge_Profile_Jul_06_2021_00-35.tgz
rm /home/admn/Downloads/Test/Edge_Profile_Jul_07_2021_00-35.tgz
....
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new)
skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new)
....
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_01_2021_00-35.tgz
rm /home/admn/Downloads/Test/Firefox_Profile_Jul_02_2021_00-35.tgz
....
實際運行腳本時在日誌檔案中輸出,不含echo
:
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_12_2021_00-35.tgz (too new): No such file or directory
/home/admn/Downloads/cleanup.sh: line 24: skipping /home/admn/Downloads/Test/Edge_Profile_Jul_13_2021_00-35.tgz (too new): No such file or directory
....
目錄中文件總數:20個文件
1、Edge_Profile_*.tgz:7月06日至7月17日:12個文件
2、Firefox_Profile_*.tgz:7月01日至7月8日:8個文件
問題:
(1) 我思考該腳本可以工作,但我不確定,因為我在不知道發生了什麼的情況下修改了大部分內容。
(2) 輸出到日誌檔:
我希望日誌檔案中的輸出與我得到的完全相同echo
,除了檔案名稱(不包含完整路徑),例如:
rm Edge_Profile_Jul_11_2021_00-35.tgz
skipping Edge_Profile_Jul_12_2021_00-35.tgz (too new)
作業系統:Ubuntu MATE 21.04
多謝。
答案1
在允許您直接存取檔案的 shell 中,根據修改時間操作檔案要容易得多。 zsh 就是這樣一種 shell。只需sudo apt install zsh
安裝即可。由於您的檔案似乎位於一個目錄中,因此該答案是非遞歸的。首先示範更簡單的情況:
要保留 Firefox_Profile_*.tgz 的最新副本並刪除其餘部分,無論它們有多舊:
echo would rm -v -- Firefox_Profile_*.tgz(.om[2,-1])
echo would
如果看起來正確,請刪除該部分。這使用了一個glob(通配符)限定符在括號內做三件事:- 僅選擇純檔案(不是目錄或套接字等)
.
- 依修改時間對文件進行排序(排序),從最新到最舊,
om
- 選擇結果清單的一部分,從第二個元素開始到結尾-跳過第一個(最新)文件,
[2,-1]
如果沒有匹配的文件,zsh 將停止並抱怨“zsh:找不到匹配項”,並且不會執行
rm
.- 僅選擇純檔案(不是目錄或套接字等)
要保留 Edge_Profile_*.tgz 的最新副本並僅在其餘內容超過 5 天時刪除它們,首先我們獲取最新的副本:
newest=(Edge_Profile_*.tgz(.om[1]))
……然後我們得到超過五天的:
older=(Edge_Profile_*.tgz(.m+5))
這裡的新部分是
+5
onm
修飾符。這將選擇超過 5 天的文件。之後,我們確保最新的不在要刪除的清單中:remove=("${(@)older:|newest}")
這裡的新部分是數組減法符號
:|
;它記錄在zsh手冊的參數擴充部分。它選擇不在“最新”中的“較舊”元素。最後,我們刪除該文件列表:echo would rm -v -- "${remove[@]}"