可以在“at”命令中執行大括號擴展嗎?
在
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
以這種方式使用命令時如何執行大括號擴展?除了我作為答案發布的解決方案之外,我有興趣查看其他解決方案,例如能夠
bash
在at
提示符中執行命令。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
讀取第一行並執行bash
,bash
然後讀取標準輸入的其餘部分作為其命令。這是非常脆弱的,但在它工作時是侵入性最小的版本。
dash
在這方面,它本身比許多 shell 更複雜,填充內部緩衝區對它來說更重要。其他簡單的 shell,例如 BusyBox 的sh
,往往具有行緩衝行為。最後,儘管您從不需要使用單獨的腳本文件,但在許多情況下,它實際上會是更好的選擇,而不是試圖在事情上過於聰明。當您的工作是一次性使用或以程式方式生成時,這些都是合理的選擇,但任何其他時間吸收它並使用獨立腳本在維護方面可能是值得的。
我真的不推薦使用最後一個選項的標準輸入,但這是一個可愛的技巧。