假設我有一個名為的文件list_of_files.txt
,其中每一行對應於磁碟上的一個文件。例如:
dir1/fileA.ext1
dir1/subdir1/fileB.ext2
fileC.ext3
dir2/fileD.ext4
fileE.ext5
我想從該列表中隨機選擇一些文件並為它們計算cksum
或。md5sum
我知道我可以使用 隨機選擇 3 個文件shuf -n 3 list_of_files.txt
,但如何將cksum
它們視為文件名而不是文字內容?
答案1
如果檔案中的路徑以換行符號終止並按原樣提供,即如果每一行都是單獨的逐字路徑,則 shell 循環將執行以下操作:
shuf -n 3 list_of_files.txt | while IFS= read -r pth; do
cksum "$pth"
done
還有xargs
(參見POSIX規範以及更先進的GNUxargs
), 有GNUparallel
(筆記非 GNUparallel
存在我不是指它)。使用正確的工具和適當的選項,您可以使一個cksum
進程多於一條路徑(產生較少的cksum
進程通常是有益的)或cksum
並行運行兩個或多個進程。
為了處理最少三個文件,由於可移植性,我可能會堅持使用 shell 循環;除非檔案很大,我預期並行運行的三個進程比一次運行cksum
一個進程要快得多。cksum
我不是 GNU 專家parallel
,但解決方案似乎很簡單:
shuf -n 3 list_of_files.txt | parallel cksum
預設情況下,GNUparallel
透過 CPU 核心數量限制同時作業的數量。現在三個或更多核心很常見,因此該命令可能會cksum
並行運行三個進程。從形式上來說,這不是可移植的。另請注意,並行處理三個檔案意味著並行讀取三個檔案。 I/O 可能是一個瓶頸,這可能會降低並行作業的好處,甚至使事情變得更糟。
即使那樣也parallel
可能有用。用於-j 1
將作業數量限制為 1:
shuf -n 3 list_of_files.txt | parallel -j 1 cksum
這些檔案將像我們的 shell 循環一樣按順序處理,但語法更簡單。對於我們的 shell 循環,你需要知道你想要的IFS= read -r pth
, 不只是read pth
;你需要知道你(在許多外殼中)想要cksum "$pth"
, 不是cksum $pth
。使用 GNU 的解決方案parallel
不太容易出錯。吻。
Note預設xargs
解釋引號和反斜杠,並將空格視為分隔符號。這意味著shuf -n 3 list_of_files.txt | xargs cksum
可能不是您想要的。您的範例可以工作,但通常您需要在文件中添加額外的引號和/或反斜線; xor 你需要xargs -d '\n'
where-d
是 GNU 的不可移植選項xargs
。我的假設是“文件中的路徑以換行符號終止並按原樣提供”。有了這個假設,GNUparallel
就可以開箱即用(即沒有附加選項),而 xargs 則不然。使用 GNUxargs
你可以這樣做:
shuf -n 3 list_of_files.txt | xargs -d '\n' cksum
如果您可以使用 GNU xargs
(以挽救局面-d '\n'
),那麼您可能可以使用 GNU parallel
。如果您-j 1
在使用 GNU 時忘記了parallel
,該命令的效能可能會更差,但它仍然可以工作。如果您-d '\n'
在使用 GNU 時忘記了xargs
路徑名稱是按原樣提供的,那麼這是一個錯誤。這就是為什麼我parallel
首先推薦GNU。
GNU 並行能夠處理以 null 結尾的字串(選項是),GNU (而不是)和 GNU (帶有)-0
也是如此。您的輸入檔使用換行符終止的行,但如果您需要使用(可能)包含換行符的路徑名,那麼更改檔案中的終止符並添加正確的選項是可行的方法。xargs
-0
-d '\n'
shuf
-z