我在高級目錄中有幾個子目錄。每個子目錄都有幾個檔案和一個for循環shell腳本。每個子目錄中都存在相同的 for 迴圈腳本。我想進入每個子目錄並在多個終端中並行運行 for 循環腳本。我嘗試了這個,但它似乎是串行執行的(一個接一個),但我想並行運行所有這些。
find dir_* -type f -execdir sh for_loop.sh {} \;
答案1
假設這做了正確的事情 - 僅以串行方式:
find dir_* -type f -execdir sh for_loop.sh {} \;
那麼你應該能夠將其替換為:
find dir_* -type f | parallel 'cd {//} && sh for_loop.sh {}'
要在多個終端機中運行它,GNU Parallel 支援在其自己的窗格tmux
中運行每個命令:tmux
find dir_* -type f | parallel --tmuxpane 'cd {//} && sh for_loop.sh {}'
預設情況下,每個 CPU 核心執行一項作業。在您的情況下,您可能希望比您擁有的核心多運行一項作業:
find dir_* -type f | parallel -j+1 --tmuxpane 'cd {//} && sh for_loop.sh {}'
GNU Parallel 是一個通用並行器,可以輕鬆地在同一台電腦或多台您可以透過 ssh 存取的電腦上並行運行作業。
如果您想要在 4 個 CPU 上執行 32 個不同的作業,則並行化的直接方法是在每個 CPU 上執行 8 個作業:
相反,GNU Parallel 在完成後會產生一個新進程 - 保持 CPU 處於活動狀態,從而節省時間:
安裝
出於安全原因,您應該使用軟體套件管理器安裝 GNU Parallel,但如果 GNU Parallel 未針對您的發行版打包,您可以進行個人安裝,這不需要 root 存取權限。這樣做可以在 10 秒內完成:
$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh
其他安裝選項,請參閱http://git.savannah.gnu.org/cgit/parallel.git/tree/README
了解更多
查看更多範例:http://www.gnu.org/software/parallel/man.html
觀看介紹影片:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
瀏覽本教學:http://www.gnu.org/software/parallel/parallel_tutorial.html
註冊電子郵件清單以獲得支援:https://lists.gnu.org/mailman/listinfo/parallel
答案2
也許最完美的工具是GNU 平行:
parallel ::: dir_*/for_loop.sh
GNU Parallel 不僅並行運行每個作業,而且還對它們的輸出進行多路分解,這樣它們就不會互相干擾。
從其手冊頁:
GNU並行是一種shell工具,用於使用一台或多台電腦並行執行作業。作業可以是單一命令或必須針對輸入中的每一行運行的小腳本。典型的輸入是檔案清單、主機清單、使用者清單、URL 清單或表格清單。作業也可以是從管道讀取的命令。然後,GNU並行可以將輸入分割成區塊,並將區塊並行地傳送到每個命令中。
如果您今天使用 xargs 和 tee,您會發現 GNU 並行非常易於使用,因為 GNU 並行被編寫為具有與 xargs 相同的選項。如果你在shell中寫循環,你會發現GNU並行可能能夠取代大部分循環,並透過並行運行多個作業使它們運行得更快。
GNU 並行確保指令的輸出與順序運行指令時得到的輸出相同。這使得可以使用 GNU 並行的輸出作為其他程式的輸入。
答案3
find
不會為你做那件事。
建立一個腳本,找到 for_loop.sh 腳本並執行它們,如下所示:
#!/bin/bash
for theScript in $(find dir_* -name for_loop.sh); do
"$theScript" &
done
如果腳本必須在子目錄內運行,請嘗試cd
進入之前,也許像cd $(dirname "$theScript") && . $(basename "$theScript")
.
我的例子沒有經過詳細測試並且不具有容錯性...
編輯1:
作為佐藤桂註解正確,如果目錄名稱中有空格,上面的腳本就會中斷。
所以我改為循環read
:
#!/bin/bash
find dir_* -name for_loop.sh | while IFS= read -r theScript; do
"$theScript" &
done
答案4
你可以從你的頂級目錄做
for D in `find . -type d -maxdepth 1`
do
$D/<yourScriptName>.sh &
done
「&」是在後台運行它們