
我想透過終端打開隨機選擇的檔案。我發現shuf
,這似乎正是我需要的實用程序,儘管我無法找到一種方法來使我正在使用的命令遞歸。
最初我使用了open $(ls | gshuf -n1)
,如果我有一個扁平的目錄結構,它會很好用。如何使此遞歸到任意數量的子目錄並過濾掉檔案.DS_Store
和資料夾?
答案1
正確的工具是find
.它遞歸地工作,這解決了您的主要問題。如果您知道如何的話,您可以排除各種模式。
基本用法如下:
open "$(find . -type f | shuf -n1)"
檔案名稱中的換行符號會打破這一點。您的工具可能支援也可能不支援允許傳遞 NUL 終止資料的非 POSIX 選項。這段程式碼在我的 Debian 中有效:
find . -type f -print0 | shuf -z -n1
儘管如果將其嵌入到 中$(…)
,尾隨換行符(如果有)仍將被刪除。
若要排除名稱,您可以使用類似 的語法! -name .DS_Store
,但要排除您需要的整個子目錄-prune
。有陷阱:
- 操作數的順序很重要,例如
-prune
對於目錄來說應該在 之前-type f
,-print
/-print0
通常屬於最後。 - 邏輯「或」(
-o
)通常需要括號而且它並不像您希望的那樣直觀。 - 省略
-print
/-print0
可能會為您帶來比您預期更多的結果。對於複雜的邏輯,最好明確包含-print
/-print0
。
學習man 1 find
以了解更多。這是一個不包括兩個目錄和兩個名稱模式的工作範例:
find . \( -name dir1 -o -name "dir 2" \) -prune -o -type f ! \( -name "*.txt" -o -name "echo*" \) -print
既然你需要$(…)
並且我告訴你正確引用,你應該知道裡面的引號$(…)
是單獨解析的。例如,這是正確引用的:
open "$(find . -type f ! -name "not this file" | shuf -n1)"
(比較這個答案,怪癖2)。