Shell

可以在“at”命令中執行大括號擴展嗎?

  • March 23, 2015

bash中,大括號擴展在執行命令之前作為 shell 操作執行。1這意味著以下將起作用:

echo {1..10} >output | at -m now

輸出將是1 2 3 4 5 6 7 8 9 10.

不起作用的是嘗試在命令中執行大括號擴展,該at命令警告命令將由 執行/bin/sh,在我的情況下,它連結到dash似乎不支持使用大括號進行範圍擴展。

$ at - now
warning: commands will be executed using /bin/sh
at> echo {1..10} >output
at> <EOT>

這將在dash(或 Bourne 或您/bin/sh連結到的任何 shell)中執行命令,從而產生輸出{1..10}

at以這種方式使用命令時如何執行大括號擴展?


除了我作為答案發布的解決方案之外,我有興趣查看其他解決方案,例如能夠bashat提示符中執行命令。at為從提示符執行的每個單行命令創建腳本似乎比必要的工作量更大。

還有三個直接的其他選項。一個有點脆弱,依賴於 shell 的實現細節,另一個使用這裡的文件來提供腳本來bash內聯,另一個只是-c用來傳遞一行。


最可靠和便攜,使用這里文件

$ at now
warning: commands will be executed using /bin/sh
at> bash <<'EOF'
at> echo {1..5} >/tmp/output
at> EOF
at> <EOT>
job 24 at Mon Mar 23 20:41:20 2015
$ cat /tmp/output
1 2 3 4 5

<<word聲明一個 here 文件,該文件作為標準輸入提供bash並持續到word. 通過引用'EOF'文件不受外殼擴展,所以你可以$在正文中寫一個而dash不吃它。EOF您的腳本可以在行首包含除(或您選擇的詞)以外的任何內容。

這確實是我推薦的方法——您幾乎可以像一直在使用一樣編寫它bash,只需在開頭和結尾添加一行以顯示正在發生的事情。


如果它真的只是一行,只需使用bash -c傳遞一個命令來執行:

$ at now
warning: commands will be executed using /bin/sh
at> bash -c 'echo {1..3} >/tmp/output'
at> <EOT>
job 25 at Mon Mar 23 20:50:03 2015
$ cat /tmp/output
1 2 3

當您在命令中也有要使用的引號時,這可能會有點麻煩。


最駭人聽聞的是:atd通常將作業作為標準輸入發送到外殼(但我不相信它是必需的)。Shell 通常逐行讀取標準輸入(但它們不需要以這種方式執行)。

如果您的實現確實以這種方式執行,那麼您可以執行一個討厭的技巧來在另一個 shell 下執行您的作業:

$ at now
warning: commands will be executed using /bin/sh
at> bash
at> echo {1..10} >/tmp/output
at> <EOT>
job 22 at Mon Mar 23 20:40:00 2015
$ cat /tmp/output
1 2 3 4 5 6 7 8 9 10

這是有效的,因為sh讀取第一行並執行bashbash然後讀取標準輸入的其餘部分作為其命令。這是非常脆弱的,但在它工作時是侵入性最小的版本。

dash在這方面,它本身比許多 shell 更複雜,填充內部緩衝區對它來說更重要。其他簡單的 shell,例如 BusyBox 的sh,往往具有行緩衝行為。


最後,儘管您從不需要使用單獨的腳本文件,但在許多情況下,它實際上會是更好的選擇,而不是試圖在事情上過於聰明。當您的工作是一次性使用或以程式方式生成時,這些都是合理的選擇,但任何其他時間吸收它並使用獨立腳本在維護方面可能是值得的。

我真的不推薦使用最後一個選項的標準輸入,但這是一個可愛的技巧。

引用自:https://unix.stackexchange.com/questions/191930