使用glob 限定符可以以zsh
各种方式对文件名通配模式匹配的结果进行排序。例如,该模式*(om)
将匹配当前目录中的所有非隐藏名称,按修改时间戳排序。
但是,我有时想要一种随机排序的方法(例如,获取文件的随机抽样)。据我所见,没有直接执行此操作的限定符。
问题:如何从zsh
文件名通配模式中获取路径名的随机列表?
使用glob 限定符可以以zsh
各种方式对文件名通配模式匹配的结果进行排序。例如,该模式*(om)
将匹配当前目录中的所有非隐藏名称,按修改时间戳排序。
但是,我有时想要一种随机排序的方法(例如,获取文件的随机抽样)。据我所见,没有直接执行此操作的限定符。
问题:如何从zsh
文件名通配模式中获取路径名的随机列表?
使用随机排序键(glob 限定符
oe
)::解释:
oe
后跟一个字符分隔符、一段代码和另一个分隔符。代码块可能不包含分隔符。特殊字符需要转义,以便在解析 glob 限定符本身时不解析它们。'
其用作分隔符(使用反斜杠,因为它需要转义),并且我用它包装代码'
以保护可能存在的特殊字符。这样我就可以编写任意代码,只要它不包含'
.REPLY
最初设置为文件名,而代码设置REPLY
的任何内容都用作排序键)。要随机采样
$n
元素,请添加[…]
限定符:有时,某些元素会获得相同的排序键,因此所有排列的可能性并不相同,稍微倾向于保留将排序函数应用于目录顺序列表的任何结果¹,但偏差很小。我
$RANDOM,$RANDOM
用作排序键而不是$RANDOM
减少偏差:$RANDOM
是一个 15 位数字,当文件数接近 2^15 时,偏差会很明显。请注意,
$RANDOM
如果轻微偏差不是问题,这对于采样来说已经足够了。它不适合任何涉及安全的事情。如果您想要一个安全的随机排列,请使用 GNU coreutils 的shuf
. (如果您最喜欢的操作系统缺少原生操作系统shuf
,并且由于某种原因不想安装 GNU coreutils,您可以尝试使用 ibara 的重新实现。)或更简单的版本可能会遇到命令行长度限制:
¹在实验上排序是稳定的(例如
*(omoe\''REPLY=1'\')
,相当于*(om)
,但来自的顺序*(oe\''REPLY=1'\')
不匹配*(oN)
。无论如何,这是有利于某些特定顺序的小偏差。