Jos*_*Lee 161
这是一个使用GNU sort的随机选项的脚本:
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
Run Code Online (Sandbox Code Playgroud)
Nor*_*ame 89
你可以使用shuf
(来自GNU coreutils包).只需输入一个文件名列表,并要求它从随机排列中返回第一行:
ls dirname | shuf -n 1
# probably faster and more flexible:
find dirname -type f | shuf -n 1
# etc..
Run Code Online (Sandbox Code Playgroud)
调整该-n, --head-count=COUNT
值以返回所需行数.例如,要返回5个随机文件名,您将使用:
find dirname -type f | shuf -n 5
Run Code Online (Sandbox Code Playgroud)
gni*_*urf 18
以下是一些不解析输出的可能性,ls
对于名称中带有空格和滑稽符号的文件,这些可能性是100%安全的.所有这些都将randf
使用随机文件列表填充数组.printf '%s\n' "${randf[@]}"
如果需要,可以轻松打印此阵列.
这个可能会多次输出相同的文件,N
需要事先知道.在这里我选择N = 42.
a=( * )
randf=( "${a[RANDOM%${#a[@]}]"{1..42}"}" )
Run Code Online (Sandbox Code Playgroud)
此功能没有很好的记录.
如果事先不知道N,但你真的很喜欢以前的可能性,你可以使用eval
.但它是邪恶的,你必须确保N
不经过彻底检查就直接来自用户输入!
N=42
a=( * )
eval randf=( \"\${a[RANDOM%\${#a[@]}]\"\{1..$N\}\"}\" )
Run Code Online (Sandbox Code Playgroud)
我个人不喜欢eval
这个答案!
使用更简单的方法(循环):
N=42
a=( * )
randf=()
for((i=0;i<N;++i)); do
randf+=( "${a[RANDOM%${#a[@]}]}" )
done
Run Code Online (Sandbox Code Playgroud)如果您不希望多次使用同一个文件:
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
Run Code Online (Sandbox Code Playgroud)注意.这是旧帖子的迟到答案,但是接受的答案链接到显示可怕的bash练习的外部页面,而另一个答案并不是更好,因为它也解析了输出ls
.对接受的答案的评论指出了Lhunath的一个很好的答案,它显然表现出良好的实践,但并没有完全回答OP.
ls | shuf -n 10 # ten random files
Run Code Online (Sandbox Code Playgroud)
一种简单的解决方案,用于选择5
随机文件,同时避免解析ls.它还适用于包含空格,换行符和其他特殊字符的文件:
shuf -ezn 5 * | xargs -0 -n1 echo
Run Code Online (Sandbox Code Playgroud)
替换echo
为要为文件执行的命令.
这是对@gniourf_gniourf 迟到的回答的更晚的回应,我只是赞成,因为它是迄今为止最好的答案,两次。(一次是为了避免eval
,一次是为了安全的文件名处理。)
但是我花了几分钟来解开这个答案使用的“没有很好记录的”功能。如果您的 Bash 技能足够扎实,可以立即看到它是如何工作的,那么请跳过此评论。但我没有,并且解开它我认为值得解释。
功能#1是shell 自己的文件globbing。a=(*)
创建一个数组,$a
,其成员是当前目录中的文件。Bash 理解文件名的所有奇怪之处,因此可以保证列表正确,保证已转义等。无需担心正确解析ls
.返回的文本文件名。
功能#2是击参数扩展为阵列,一个嵌套在另一个。这以 开头${#ARRAY[@]}
,它扩展到 的长度$ARRAY
。
然后使用该扩展为数组添加下标。在 1 和 N 之间找到随机数的标准方法是取随机数的值对 N 取模。我们想要一个介于 0 和数组长度之间的随机数。这是方法,为清楚起见分为两行:
LENGTH=${#ARRAY[@]}
RANDOM=${a[RANDOM%$LENGTH]}
Run Code Online (Sandbox Code Playgroud)
但是这个解决方案在一行中完成,删除了不必要的变量赋值。
功能 #3是Bash 大括号扩展,尽管我必须承认我并不完全理解它。括号扩展使用,例如,产生的25个文件命名列表filename1.txt
,filename2.txt
等等:echo "filename"{1..25}".txt"
。
上面子shell 中的表达式"${a[RANDOM%${#a[@]}]"{1..42}"}"
,使用这个技巧产生了42 个单独的扩展。大括号扩展在 the]
和 the之间放置一个数字}
,起初我认为它是数组的下标,但如果是这样,它前面会有一个冒号。(它也会从数组中的一个随机位置返回 42 个连续的项目,这与从数组中返回 42 个随机项目完全不同。)我认为这只是让 shell 运行扩展 42 次,从而返回数组中的 42 个随机项。(但如果有人能更全面地解释它,我很想听听。)
N 必须硬编码(到 42)的原因是大括号扩展发生在变量扩展之前。
最后,这是Feature #4,如果您想对目录层次结构递归执行此操作:
shopt -s globstar
a=( ** )
Run Code Online (Sandbox Code Playgroud)
这将打开导致递归匹配的shell 选项**
。现在您的$a
数组包含整个层次结构中的每个文件。
如果您安装了Python(适用于Python 2或Python 3):
要选择一个文件(或任意命令中的一行),请使用
ls -1 | python -c "import sys; import random; print(random.choice(sys.stdin.readlines()).rstrip())"
Run Code Online (Sandbox Code Playgroud)
要选择N
文件/行,请使用(注意N
在命令末尾,用数字代替)
ls -1 | python -c "import sys; import random; print(''.join(random.sample(sys.stdin.readlines(), int(sys.argv[1]))).rstrip())" N
Run Code Online (Sandbox Code Playgroud)
如果要将这些文件的示例复制到另一个文件夹:
ls | shuf -n 100 | xargs -I % cp % ../samples/
Run Code Online (Sandbox Code Playgroud)
显然首先要创建示例目录。
归档时间: |
|
查看次数: |
85600 次 |
最近记录: |