題 如果文件不存在,如何讓rm不給出錯誤?


我正在編寫一個makefile,它將在編譯結束時清理一些無用的文件。如果已經製作了目標,它當然會跳過該目標,並且可能不存在無用文件。所以,如果我這樣做:

rm lexer.ml interpparse.ml interpparse.mli

我可能會收到錯誤,因為其中一個文件不存在。有什麼方法可以告訴你 rm 忽略這些文件?

在閱讀手冊頁時,我看到以下選項:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

聽起來像 幾乎 我想要什麼,但我不確定權限部分。有沒有辦法做到這一點?


273
2017-11-27 16:43


起源


你試過一些嗎? rm 在沙盒中?看起來像 -f 完全符合你的要求,不管是什麼樣的。 - JMD
如果權限不允許,rm將與 -f 選項仍然嘗試刪除它。它會失敗。它不會告訴你它失敗了。如果文件名是變量或glob,則很有用。 - LawrenceC


答案:


-f 選項肯定是你想要使用的。

它引用的文件權限的確認是這樣的:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

所以 rm 如果您嘗試刪除沒有寫入權限的文件,則會發出警告。如果您對目錄具有寫權限但允許這有點奇怪,則允許這樣做 rm 通常會警告你。


231
2017-11-27 16:54



大多數但不是所有系統都會問(我認為)。有些要求 -i。 - DaveParillo
如果您想要錯誤消息,而不是錯誤退出代碼,請參閱答案 吉爾伯克斯。我用 set -e 在我的所有bash腳本中,以便在任何命令發出錯誤後退出腳本。我經常想要一個腳本告訴我是否 rm 給出了錯誤,但無論如何都要繼續。繼續。 - cledoux


另一個解決方案就是這個: https://stackoverflow.com/questions/11231937/bash-ignoring-error-for-a-particular-command

只需在命令後添加一個OR語句:

rm -rf my/dir || true

這樣,當語句#1失敗(拋出錯誤)時,運行語句#2,這很簡單 true


87
2018-03-09 12:39



它打印錯誤並繼續執行,這是我的情況所需要的。 - worldsayshi
要不就 rm -rf my/dir ||: 更簡潔(: 是的縮寫 true) - Godsmith
在我看來,更好的解決方案。它很容易看到發生了什麼以及為什麼忽略結果代碼。我喜歡! - Mavamaarten


我遲到了,但我一直都在使用這個。在makefile中,添加 - 到一行的開頭,忽略該行的返回值。像這樣:

-rm lexer.ml interpparse.ml interpparse.mli

72
2017-12-23 23:12



這仍然會向控制台輸出錯誤,這會讓你忽略make輸出中的錯誤,這可能不是你想要的。在我看來,rm -rf是更好的選擇。 - Godsmith
@Godsmith我寧願忽略錯誤而不是強制遞歸刪除。這可能非常頑皮。並且為makefile特定語法+1 - Daishi
如果rm -rf可能是“頑皮”,則意味著您在版本控制下的目錄外使用make。為什麼? - Godsmith
請提供文檔鏈接。可以找到此功能的說明。 - George Sovetov
@GeorgeSovetov gnu.org/software/make/manual/make.html#Errors - Robert Li


如果您不想使用-f選項,則替代方法是:

rm filethatdoesntexist 2> /dev/null 

這樣可以防止錯誤打印。


8
2018-06-12 19:46



不幸的是,這仍然會給出錯誤退出代碼。 - Shaun McDonald


如果你找到了一些方法 glob的 文件名, rm 如果找不到匹配,不會抱怨。所以像 lexer.m* interpparse.*等等應該適合你(當然,小心你不要刪除太多)。也, -f 是一種非常合理的方式,只要您不希望文件權限可以避免刪除您不想刪除的文件 - 如果您不想刪除它,請不要將其放入名單。


7
2017-11-27 16:48



由於存在一個我不想刪除的lexer.mll文件,因此無法實現全局操作。謝謝你說明為什麼-f是合理的。我想在經過太多誤導之後我會過於小心 sudo rm -rf 。 - Jason Baker
甚至沒有更嚴格的限制 lexer.m? ...?那會抓住 lexer.ml 和 lexer.mz, 但不是 lexer.mll 要么 lexer.mla。 - JMD
@JMD:我想這取決於你的shell以及它為globbing提供的模式匹配支持。 - Nick Bastin


-f選項表示如果某些內容不符合預期,則不會提示您。這並不意味著不考慮權限。

如果您沒有足夠的權限刪除文件,則不會刪除該文件。

,如果您有足夠的權限來更改權限,您的文件將被刪除。如果您是擁有所有者的只讀權限的文件的所有者(-r --------),則會出現這種情況。作為所有者,你可以 chmod u+w,然後刪除它: rm -f 將刪除該文件。


5
2017-11-27 19:27





也許可以幫助類似的線:

touch fakefile.exe fakefile.o && rm *.o *.exe

我知道這不是很聰明,但它確實起到了作用。


3
2018-03-11 10:36





替代:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

太糟糕的Makefile不能跨行共享shell函數定義。


2
2017-11-27 17:44



您是否嘗試在行尾使用\(反斜杠)讓它繼續下一行? - some
@some:是的,它們可以分佈在多行中,但要在配方中共享它們,您必須將定義放在make變量中。 - reinierpost


這是我在shell腳本中使用的內容。它隱藏了錯誤消息和錯誤代碼。

rm doesnotexist 2> /dev/null || echo > /dev/null

2
2018-06-11 13:55