2013-11-24 69 views
8

我想在shell腳本中獲得以下C代碼的等效代碼。如何在文件不存在的情況下執行某些命令?

if(!exist) { 
    command; 
    command; 
} 
else { 
    command; 
    command; 
} 

我想更準確地在這個shell腳本中檢查文件是否存在,然後創建它。

另外,我真的很抱歉,如果這是另一個問題的重複,但我真的不知道如何搜索它。

+2

如果你對bash腳本感興趣,很好的資源是http://www.tldp.org/LDP/abs/abs-guide.pdf –

+0

謝謝你,隊友!說實話,我認爲這將是Stack Exchange的正確部分來回答這類問題。 –

+2

它是正確的地方。你的問題是關於這裏的話題,@Patrick shell腳本是明確的[在主題](http://unix.stackexchange.com/help/on-topic)。 SO shell腳本問題很容易在噪聲中丟失,你可以問他們哪裏感覺更舒適。 – terdon

回答

14

您可以使用此:

 
if [ ! -e "$file" ]; then 
     touch file 
else 
     ... 
fi 
+0

race-condition-city,有沒有辦法使用一個標誌,比如'touch -e file',如果該文件已經存在,它會以1退出? –

7
if [ ! -e "$path" ] 
then 
    touch -- "$path" 
fi 

一個簡單的版本是簡單地touch -- "$path" - 它會創建文件,如果它不存在,如果確實存在,它只是更新的訪問和修改時間。 double dash--)確保您可以創建該文件,即使它以破折號開頭,quotes$path是必要的。

+0

非常感謝!我無法接受解決方案,因爲我沒有足夠的聲望 –

16

檢查文件是否存在,是一種很常見的任務。要搜索相關問題,請使用搜索欄(右上角)。我lots of results與術語「bash腳本文件存在」

在任何情況下,你想要麼test內置或者其語義等效[ ]

[ ! -e your_file ] && >your_file 

test ! -e your_file && >your_file 

這將第一testyour_file不存在(!)存在(-e)並創建它,如果是這種情況。

有關不同的測試,你可以運行(除-e等)的更多信息,你可以輸入:

help -m test | less 
+3

您也可以使用短路評估,如'[-e your_file] || > your_file' – Useless

7

不要做,它不僅受競爭條件,而且還[ -e /path/file ]檢查如果你可以在一個文件上做一個stat(2),所以它會因爲不同的原因返回false,這不僅僅是因爲文件不能存在。

一個示例是不存在的文件的符號鏈接,或者您不具有搜索權限的目錄中的文件。

一個更好的方法是在這裏使用正確的標記來調用open(2)系統調用,即O_CREAT|O_EXCL。這樣,如果文件不存在,open()會失敗,而您不必先檢查幾百萬個CPU時鐘節拍。

隨着類似Bourne殼:

if (set -C && : > "$file") 2> /dev/null; then 
    print '%s\n' "$file has been created 
else 
    print '%s\n' "It hasn't, possibly because it was already there" 
fi 

set -C是使O_EXCL標誌)。

另外,你爲什麼要創建一個空文件?有可能你想在該文件中存儲一些東西。然後,只要做到這一點:

set -C 
{ 
    echo blah 
    other-commands that-generate-the-content 
} > "$file" 

然後,如果file不存在該指令組僅執行(並有可能創建一個)。

如果你想測試文件的存在,但至少寫:

[ -e "$file" ] || [ -L "$file" ] 

ls -d -- "$file" > /dev/null 2>&1 

,如果你關心它可能是一個符號鏈接。如果文件確實存在但仍然無法驗證,則仍然會返回false。


現在,如果你想了解測試一個較長的歷史應答文件的存在:

最初,test命令(在Unix的V7它第一次出現)had no -e (nor -h/-L option or -a unary)選項。

測試文件存在的方法是使用lsls(與-d)列出該文件並報告錯誤(並返回錯誤退出狀態),如果由於某種原因無法查找該文件。 Unix最初沒有符號鏈接,但是當它們被引入時,ls被修改爲在文件上執行lstat(2)而不是stat(2)。也就是說,如果符號鏈接ls返回有關符號鏈接文件本身的信息,而不是符號鏈接指向的路徑中的文件。

test(又名[)進行測試的選項文件「存在」首先在Korn shell test builtin介紹。那是-a,而不是-e-a適用於(我相信)這是一個比現有更準確的術語。

我不知道什麼時候介紹-e,可能是POSIX。 POSIX says-e被選爲-a以避免與-a二進制運營商(對於)可能的混淆。

在任何情況下的文件,而不是一個lstat(2)-a-e嘗試stat(2)。那就是:

[ -e "$file" ] 

等同於:

ls -Ld -- "$file" > /dev/null 2>&1 

所以,嚴格來說,它返回true,如果在測試做的時候,有可能解決的符號鏈接後查找路徑,如果stat(2)失敗,則忽略失敗的原因。

stat如果該文件不存在(ENOENT),即文件不存在或存在,但是它是不存在的文件的符號鏈接,但也有很多其他原因可能會失敗。看着the possible error codes of stat(2)給出了幾點建議:

  • EACCESS:路徑的分辨率時(這可以是任何路徑組件,並在任何符號鏈接的路徑),你不必搜索權限一個目錄組件(請注意,您可能仍然可以通過其他路徑訪問該文件)。
  • ELOOP:由於太多符號鏈接解析到達那裏,因此無法解析路徑。
  • ENOTDIR。例如在/etc/passwd/foo或其符號鏈接。
+1

聲稱它的競爭條件是不成熟的。 OP沒有說明這個文件來自哪裏,腳本可能是唯一能夠創建它的東西。還說不應該使用'[-e/path/file]',因爲它可能會錯誤地失敗並不是一個好的參數。如果測試錯誤地失敗並嘗試創建文件,則創建將會出錯。通過刪除測試並使用O_EXCL,創建將會出現與測試具有完全相同原因的錯誤。另外它可能是一個創建文件的程序,其中'set -C'不會阻止程序覆蓋它。 – Patrick

+1

@Patrick。否,如果文件是符號鏈接到現有目錄中不存在的文件,則「[-e」$ file「]'將返回false,則創建將成功,而不會生成O_EXCL(這是危險的,因爲攻擊者可以強制您創建文件,你不會想要),並會失敗,O_EXCL(這意味着沒有關注)。 –

+0

另外,對於OP來說可能是「過早」。很可能他一次只運行腳本的一個實例,沒有別的東西可以寫入該文件,該文件處於非常溫和的區域,只有一個用戶有寫入權限,並且該用戶永遠不會涉及處理「外國/外來/不受控制」的數據,但是在堆棧交換中,答案是針對每個人的,因此IMO應該指出風險。並且考慮到該方法更安全且更便宜(只有一個系統調用,儘管第一次分叉,沒有外部命令運行),該方法應該是優選的。 –

相關問題