將路徑封裝在引號中時,反引號不起作用
我有一個腳本,我想在超過設定限制時清除舊文件。
我有這個命令:
/bin/rm -f `/bin/ls -t $bkup_p/mysql.daily/* 2> /dev/null | /bin/awk 'NR>'5`
哪個有效,並且因為 $bkup_p 中可能有一個空格,所以我嘗試將其更改為
/bin/rm -f `/bin/ls -t "$bkup_p/mysql.daily/*" 2> /dev/null | /bin/awk 'NR>'5`
但這不起作用。它不顯示有問題的文件,它只是空的
正如其他人所說,你不應該使用
ls
它。但是,如果您的環境沒有任何更明智的東西並且您知道警告,那麼您可能會僥倖逃脫,如果您的文件名足夠好:沒有空格或不可列印的字元,尤其是 shell 解釋為萬用字元的任何內容(至少?*[]
)。使用 Perl 之類的東西對文件進行排序,或者將日期放在文件名中以便您可以依賴全域順序會更好。
話雖如此:在您的第二個片段中,引用了星號,因此不會發生通配。你會看到一個關於
some dir/mysql.daily/*
不存在的錯誤,但你沒有看到,因為你將錯誤輸出重定向了。帶有空格的文件名會給您帶來命令替換的輸出沿空格拆分的問題,因此
some dir/foo
將rm
分兩部分給出類似的內容:some
和dir/foo
. 希望它們都不存在,因為它們會被刪除。如果只有您的目錄名稱包含空格,您可以
cd
先進入它。或者,設置IFS
為僅包含換行符(而不是預設的空格、製表符、換行符)。你提到了一個 NAS,所以你很可能有busybox。這應該適用於busybox和bash,並列印文件名,每行一個:IFS=$'\n' printf "%s\n" $( ls -t "$bkup_p/mysql.daily/"* | tail -n +6 )
如果您確定它可以正常工作,請替換
printf "%s\n"
為刪除文件。rm
在修改時間過濾文件並對其執行命令時,Bash 不是很方便。
我建議改用 z-shell,所以先執行
zsh
,然後rm -i -- "$bkup_p"/mysql.daily/*(DN.Om[1,5])
這將刪除給定目錄中最舊的五個普通文件,我懷疑這可能是您想要實現的目標。顯然,在一天結束時,
rm -i
如果rm -f
需要的話。要刪除五個最新文件,請執行
rm -i -- "$bkup_p"/mysql.daily/*(DN.om[1,5])
現在,它是如何工作的。裡面的所有東西
()
都是所謂的 glob 限定符,它基本上根據您的需要過濾文件:
D
包括點文件(以 開頭的文件.
)N
如果沒有匹配則不報告錯誤.
只選擇普通文件om
按修改時間Om
排序(倒序排序)[1,5]
從列表中僅選擇五個文件我相信所有這些都應該適用於文件名中的特殊字元(空格、換行符等)