我有一個包含大約2000個文件的目錄。如何通過使用bash腳本或管道命令列表來選擇N
文件的隨機樣本?如何從bash中的目錄中選擇隨機文件?
回答
下面是一個使用GNU的排序是隨機選擇的腳本:
ls |sort -R |tail -$N |while read file; do
# Something involving $file, or you can leave
# off the while to just get the filenames
done
酷,不知道排序-R;我之前使用過bogosort :-p – alex 2009-01-05 21:23:28
排序:無效選項 - R 嘗試`sort --help'以獲取更多信息。 – 2015-10-28 06:28:42
似乎不適用於文件中有空格的文件。 – Houshalter 2017-03-17 22:46:13
這裏是不解析的ls
輸出幾種可能性,並且是100%安全的關於在空間和有趣的符號文件,其名稱。所有這些將隨機文件列表填充數組randf
。如果需要,可以使用printf '%s\n' "${randf[@]}"
輕鬆打印此陣列。
這一次很可能會輸出相同的文件幾次,
N
需要預先知道。這裏我選擇了N = 42。a=(*) randf=("${a[RANDOM%${#a[@]}]"{1..42}"}")
此功能沒有很好的記錄。
如果事先不知道N,但是您確實喜歡以前的可能性,則可以使用
eval
。但它是邪惡的,你必須確保N
不是直接來自用戶輸入,沒有徹底檢查!N=42 a=(*) eval randf=(\"\${a[RANDOM%\${#a[@]}]\"\{1..$N\}\"}\")
我個人不喜歡
eval
,因此這個答案!使用更簡單的方法相同的(循環):
N=42 a=(*) randf=() for((i=0;i<N;++i)); do randf+=("${a[RANDOM%${#a[@]}]}") done
如果你不想有可能多次相同的文件:
N=42 a=(*) randf=() for((i=0;i<N && ${#a[@]};++i)); do ((j=RANDOM%${#a[@]})) randf+=("${a[j]}") a=("${a[@]:0:j}" "${a[@]:j+1}") done
注意。對於舊帖子,這是一個遲到的答案,但接受的答案鏈接到顯示可怕的bash練習的外部頁面,而另一個答案並不好,因爲它也分析了ls
的輸出。對接受答案的評論指出,Lhunath的一個很好的答案顯然表明了良好的做法,但並沒有完全回答OP。
你可以使用shuf
(來自GNU coreutils包)。只要給它的文件名列表,並要求它從一個隨機排列返回的第一行:
ls dirname | shuf -n 1
# probably faster and more flexible:
find dirname -type f | shuf -n 1
# etc..
調整值返回想要的行數。例如,要返回5個隨機文件名,您可以使用:
find dirname -type f | shuf -n 5
這是我可以在MacOS上使用bash進行遊戲的唯一腳本。我結合,並從以下兩個鏈接編輯片段:
ls command: how can I get a recursive full-path listing, one line per file?
#!/bin/bash
# Reads a given directory and picks a random file.
# The directory you want to use. You could use "$1" instead if you
# wanted to parametrize it.
DIR="/path/to/"
# DIR="$1"
# Internal Field Separator set to newline, so file names with
# spaces do not break our script.
IFS='
'
if [[ -d "${DIR}" ]]
then
# Runs ls on the given dir, and dumps the output into a matrix,
# it uses the new lines character as a field delimiter, as explained above.
# file_matrix=($(ls -LR "${DIR}"))
file_matrix=($(ls -R $DIR | awk '; /:$/&&f{s=$0;f=0}; /:$/&&!f{sub(/:$/,"");s=$0;f=1;next}; NF&&f{ print s"/"$0 }'))
num_files=${#file_matrix[*]}
# This is the command you want to run on a random file.
# Change "ls -l" by anything you want, it's just an example.
ls -l "${file_matrix[$((RANDOM%num_files))]}"
fi
exit 0
我用這樣的:它使用的臨時文件,但目錄中的深進,直到它找到一個普通文件和回報它。
# find for a quasi-random file in a directory tree:
# directory to start search from:
ROOT="/";
tmp=/tmp/mytempfile
TARGET="$ROOT"
FILE="";
n=
r=
while [ -e "$TARGET" ]; do
TARGET="$(readlink -f "${TARGET}/$FILE")" ;
if [ -d "$TARGET" ]; then
ls -1 "$TARGET" 2> /dev/null > $tmp || break;
n=$(cat $tmp | wc -l);
if [ $n != 0 ]; then
FILE=$(shuf -n 1 $tmp)
# or if you dont have/want to use shuf:
# r=$(($RANDOM % $n)) ;
# FILE=$(tail -n +$(($r + 1)) $tmp | head -n 1);
fi ;
else
if [ -f "$TARGET" ] ; then
rm -f $tmp
echo $TARGET
break;
else
# is not a regular file, restart:
TARGET="$ROOT"
FILE=""
fi
fi
done;
如果您已經安裝了Python(可與任意的Python 2或Python 3):
要選擇一個文件(或線從任意命令),使用
ls -1 | python -c "import sys; import random; print(random.choice(sys.stdin.readlines()).rstrip())"
選擇N
文件/行,使用(注意N
位於命令的末尾,用數字代替)
ls -1 | python -c "import sys; import random; print(''.join(random.sample(sys.stdin.readlines(), int(sys.argv[1]))).rstrip())" N
這是對@ gniourf_gniourf遲到的答案的一個更晚的迴應,我剛剛提出,因爲這是迄今爲止最好的答案,兩次。 (一次爲了避免eval
,一次爲了安全的文件名處理。)
但是花了我幾分鐘才解開了這個答案使用的「沒有很好記錄」的功能。如果你的Bash技能足夠穩固,你立即看到它的工作原理,那麼跳過這個評論。但我沒有,並解開它,我認爲這是值得解釋的。
功能#1是shell自己的文件通配符。 a=(*)
創建一個數組,$a
,其成員是當前目錄中的文件。 Bash理解文件名的所有奇怪之處,以便列表保證正確,保證轉義等。無需擔心由ls
返回的正確解析文本文件名稱。
特徵#2是Bash parameter expansions爲arrays,一個嵌套在另一個。這開始於${#ARRAY[@]}
,其擴展到$ARRAY
的長度。
該擴展然後用於下標數組。尋找1到N之間隨機數的標準方法是取模隨機數N的值。我們需要一個介於0和數組長度之間的隨機數。這裏的方法,分爲兩行清晰的緣故
LENGTH=${#ARRAY[@]}
RANDOM=${a[RANDOM%$LENGTH]}
但這種方法做它在一個單一的線,去除不必要的變量賦值。
功能#3是Bash brace expansion,雖然我不得不承認我不完全理解它。例如,使用Brace擴展來生成名爲filename1.txt
,filename2.txt
等的25個文件的列表:echo "filename"{1..25}".txt"
。
上面的子shellhell中的表達式"${a[RANDOM%${#a[@]}]"{1..42}"}"
使用該技巧來產生42個單獨的擴展。括號擴展在]
和}
之間放置了一個數字,起初我以爲是對數組進行下標,但如果是這樣,則會在冒號前加上數字。(它也會從數組中的一個隨機點中返回42個連續項,這與從數組中返回42個隨機項完全不同。)我認爲這只是讓shell運行擴展42次,從而返回來自陣列的42個隨機項目。 (但是,如果有人能更充分地解釋,我很想聽聽吧。)
的原因N有被硬編碼(42)爲變量擴展前的括號擴展情況。
最後,這裏的特點#4,如果你想爲一個目錄層次結構遞歸地做到這一點:
shopt -s globstar
a=(**)
這將打開一個shell option導致**
遞歸匹配。現在您的$a
數組包含整個層次結構中的每個文件。
怎麼樣一個Perl的解決方案從康先生在這裏稍微篡改:
How can I shuffle the lines of a text file on the Unix command line or in a shell script?
$ LS | perl -MList :: Util = shuffle -e'@lines = shuffle(<>);打印 @lines [0..4]」
的簡單解決方案,用於選擇5
隨機文件,同時avoiding to parse ls。它還可以與含有空格,換行和其他特殊字符的文件:
shuf -ezn 5 * | xargs -0 -n1 echo
替換echo
您要執行的文件的命令。
ls | shuf -n 10 # ten random files
的MacOS沒有排序-R和SHUF命令,所以我需要一個bash只隨機化的所有文件沒有重複,並沒有發現,這裏的解決方案。該解決方案與gniourf_gniourf的解決方案#4類似,但希望能增加更好的評論。
腳本應該很容易修改,以便在N個樣本使用帶if的計數器後停止,或者gniourf_gniourf的for循環使用N. $ RANDOM限制爲~32000個文件,但對大多數情況應該這樣做。
#!/bin/bash
array=(*) # this is the array of files to shuffle
# echo ${array[@]}
for dummy in "${array[@]}"; do # do loop length(array) times; once for each file
length=${#array[@]}
randomi=$(($RANDOM % $length)) # select a random index
filename=${array[$randomi]}
echo "Processing: '$filename'" # do something with the file
unset -v "array[$randomi]" # set the element at index $randomi to NULL
array=("${array[@]}") # remove NULL elements introduced by unset; copy array
done
- 1. 從目錄中選擇隨機文件
- 2. 如何從目錄中隨機選擇一個文件?
- 3. 從Java目錄中選擇一個隨機文件
- 4. 隨機從PHP目錄中選擇一個文件
- 5. 從目錄中選擇隨機文本文件並從中讀取c#
- 6. 從文件中選擇隨機數據
- 7. 如何從AS3中的目錄中獲取隨機文件名?
- 8. 從mnesia中選擇隨機記錄
- 9. 如何從文本文件中選擇一條隨機線
- 10. 如何從文本文件中選擇隨機問題?
- 11. 從JavaScript Object中選擇隨機項目?
- 12. 從txt文件中隨機選擇一組項目
- 13. 如何從Coldfusion cfdirectory查詢中選擇隨機文件?
- 14. 如何從MySQL中選擇記錄的隨機樣本?
- 15. 隨機選擇PHP中的文件
- 16. 從目錄中隨機選擇一個文件,然後顯示它
- 17. 從WHILE中隨機選擇
- 18. 如何從目錄中的文件夾中選擇圖像?
- 19. 從目錄中選擇某些文件
- 20. 如何從一組隨機數中進行隨機選擇?
- 21. 如何從mysql表中隨機選擇或隨機播放它?
- 22. 如何從MySQL數據庫中選擇一條隨機記錄?
- 23. 如何從訪問表中選擇700條隨機記錄?
- 24. 如何從數組中隨機選擇項目?
- 25. 如何從2sxc數據流中選擇一個隨機項目?
- 26. 如何從數組中選擇一個隨機項目?
- 27. 從Sequelize選擇隨機記錄的findAll
- 28. 從文件系統中隨機選擇一個文件
- 29. C#從嵌入的文本文件中選擇隨機線?
- 30. 如何從選定的複選框中選擇隨機對象
在Unix和Linux上也是一個很好的答案:http://unix.stackexchange.com/a/38344/24170 – 2015-11-23 03:40:35
`ls | SHUF -n 5` [來源從Unix Stackexchange](http://unix.stackexchange.com/a/48477/14993) – jgomo3 2017-01-26 18:37:22
類似:https://stackoverflow.com/questions/2153882/how-can-i-shuffle -th-line-of-the-unix-command-line-or-in-a-shel – AAAfarmclub 2017-06-06 02:05:58