2010-08-02 60 views
3

我想要一個Perl腳本接受通配符(foo - *。ba?)作爲文件名(然後處理整個目錄子樹)。我該如何「看後面」bash命令行參數展開?

當然,我可以告訴我的腳本用戶引用參數('foo - *。ba?'),但這並不是很高雅 - 通配符方法是一種用戶友好的替代方法正則表達式(也被接受,當然,其中必須引用)。麻煩的是,shell(bash,在我的情況下)將命令行擴展爲與當前目錄中的通配符模式相匹配的文件,所以我可憐的腳本獲得了@ARGV預設值,無論bash發現了什麼(通常沒有,或者一堆foo-lotsof.baz等)。

是否有任何地方的bash未展開命令行的副本?

+0

。 – 2010-08-02 17:00:11

回答

3

恐怕沒有簡單的解決方法。 bash在執行命令之前擴展通配符。這就是爲什麼你必須引用參數find -name '*.txt' - 如果你不bash會嘗試擴大通配符,你得不到你想要的結果

+0

這是正確的。在您的程序獲取它們之前,shell會擴展它們,並且您的程序無法知道輸入是由shell擴展還是按原樣鍵入。 – bta 2010-08-02 16:58:34

+0

您也可以使用'find -name \\ * .txt'來進行轉義。但那不會讓OP更快樂。 – 2010-08-02 17:30:23

2

bash擴展通配符,然後將它們傳遞給程序。這是bash的功能,它是bash的工作方式,所以我認爲你不能找到解決方法。 (有趣的是,Windows的命令行shell並沒有擴展通配符,所以你必須做一些有點痛苦的解決方法才能讓Perl腳本按預期工作。)

引用文件名是標準解決方案,而Linux命令行用戶應該是非常熟悉它。

其他程序(如find(1))具有需要引用通配符的參數的相同問題。 (即使你可以想出一些方法從Perl腳本中查詢bash的命令行歷史記錄以便在用戶鍵入它時查找該命令,但是仍然會遇到從其他shell運行腳本的問題,其他腳本等)

+1

擴展能力可能是一項功能,但不能成爲缺陷/錯誤特徵。 – Medinoc 2014-01-03 20:47:13

+0

@Medinoc - 有能力無法展開。只需將通配符放在引號中。 – 2014-01-05 15:06:50

4

請不要嘗試解決此問題。更改參數的解釋方式由用戶在選擇引用時完成。即使你可以(並且我知道bash中有鉤子,我對此一無所知可能會使它成爲可能),但你不會以這種方式提供更好的用戶體驗,你會提供更糟的。

+0

Downvoted。如果沒有應用程序端通配符檢查可以提供的安全網,那麼沒有更糟糕的用戶體驗比做不可逆轉的文件操作。 shell對應用程序的命令行有謊言,我厭倦了人們稱這種錯誤功能爲特徵。通配符擴展應該是標準POSIX庫的一部分,而不是shell。 – Medinoc 2014-01-03 20:41:33

+0

錯誤或特徵,一致性更好(並且滿足對一致性的期望,實際上更安全,IMO)。 「應該是」不是問題。 – ysth 2014-01-03 21:26:12

4

根據bash手冊頁,你可以禁止擴展字符*,?和[用-f開關。請參閱路徑名稱擴展。

$ bash -f -c 'ls *' 
ls: *: No such file or directory 

但是,你必須要求你的用戶改變他們開始bash的方式,或者你必須試着控制這個。它只是簡單地轉移問題。

你的程序應該處理shell行爲,而不是相反。

編輯:作爲最後的評論,我想指出,使用單引號是unix shell中的常見做法,作爲防止擴展的手段。你不應該害怕和你自己的劇本一樣。

3

對於這個問題的人來說,一個額外的答案只是沒有幫助: 考慮我的解決方案來防止通配符擴展(globbing),here

它的癥結在this related answer列出。對於大多數(如果不是全部的話)Unix/Linux shell來說,[by-design]都可以使用[by-design]