我有一個bash程序將寫入輸出文件。該文件可能存在也可能不存在,但該腳本必須檢查權限並提前失敗。我找不到一個優雅的方式來實現這一點。這是我的嘗試。Bash:創建一個文件,如果它不存在,否則檢查它是否可寫
set +e touch $file set -e if [ $? -ne 0 ]; then exit;fi
我一直set -e
對這個腳本,以便它失敗,如果有過任何線上的錯誤。有沒有更簡單的方法來執行上述腳本?
我有一個bash程序將寫入輸出文件。該文件可能存在也可能不存在,但該腳本必須檢查權限並提前失敗。我找不到一個優雅的方式來實現這一點。這是我的嘗試。Bash:創建一個文件,如果它不存在,否則檢查它是否可寫
set +e touch $file set -e if [ $? -ne 0 ]; then exit;fi
我一直set -e
對這個腳本,以便它失敗,如果有過任何線上的錯誤。有沒有更簡單的方法來執行上述腳本?
,而不是在不同的線路檢查$?
,立即檢查返回值是這樣的:
touch file || exit
只要你umask
不限制被設定寫入位,你可以依靠返回值touch
您可以使用-w
來檢查文件是否可寫(在bash手冊頁中搜索它)。
if [[ ! -w $file ]]; then exit; fi
打開文件進行寫入。在shell中,這是通過輸出重定向完成的。您可以重定向shell的標準輸出,方法是將內置的參數exec
設置爲無參數。
set -e
exec >shell.out # exit if shell.out can't be opened
echo "This will appear in shell.out"
確保您沒有設置noclobber
選項(這是有用的交互,但往往無法使用的腳本)。如果要截斷文件(如果存在),則使用>
;如果要附加,則使用>>
。
如果您只想測試權限,則可以運行: >foo.out
來創建該文件(如果存在,則將其截斷)。
如果您只想要一些命令寫入文件,請在其他描述符上打開它,然後根據需要重定向。
set -e
exec 3>foo.out
echo "This will appear on the standard output"
echo >&3 "This will appear in foo.out"
echo "This will appear both on standard output and in foo.out" | tee /dev/fd/3
(/dev/fd
不支持無處不在;它可至少在Linux,* BSD,Solaris和Cygwin的。)
爲什麼複雜的事情?
file=exists_and_writeable
if [ ! -e "$file" ] ; then
touch "$file"
fi
if [ ! -w "$file" ] ; then
echo cannot write to $file
exit 1
fi
或者,更簡潔,
([ -e "$file" ] || touch "$file") && [ ! -w "$file" ] && echo cannot write to $file && exit 1
爲什麼必須在腳本的早期失敗?通過分離可寫測試和文件open(),您可以引入競爭條件。相反,爲什麼不嘗試打開(截斷/追加)文件進行寫入,並處理錯誤?喜歡的東西:
$ echo foo > output.txt
$ if [ $? -ne 0 ]; then die("Couldn't echo foo")
正如其他人更不用說了,如果你想避免覆蓋現有文件「noclobber選項」選項可能是有用的。
我必須警告你,有一個競爭條件。您無法儘早檢查錯誤。在你檢查的時候文件可能已經存在了,但是在你開始寫入文件的時候已經被刪除了。或者更糟的是,權限改變了。我建議你打開文件寫入並獲取描述符。如果那個手術成功了,那你很好。在這種情況下,文件是否被刪除並不重要,操作系統會在刪除的情況下保持inode打開,並從文件名稱中「解除」它。 – 2010-12-23 13:26:48
幫我理解。如果日誌文件在腳本運行時被刪除,那麼如果我打開描述符,嘗試寫入它就會成功?但該文件被刪除..數據去哪裏?我不希望它在這些罕見的情況下失敗嗎? – User1 2010-12-23 15:43:32
如果文件被刪除(更具體地說,未鏈接),同時打開寫入,則文件保留在文件系統中,直到所有文件句柄關閉,無論是顯式還是退出進程。如果你的進程是寫入文件的唯一東西,它將繼續填滿磁盤,但不能被任何其他進程打開(因爲沒有目錄項)。 – Phil 2010-12-23 17:28:21