假设我有一个名为的文件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
;你需要知道你(在许多 shell 中)想要cksum "$pth"
,而不是cksum $pth
。使用 GNU 的解决方案parallel
不太容易出错。吻。
注意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 parallel 能够处理以空字符结尾的字符串(选项为-0
),GNU xargs
(-0
而不是-d '\n'
)和 GNU shuf
(带-z
)也能够处理以空字符结尾的字符串。您的输入文件使用以换行符结尾的行,但如果您需要使用(可能)包含换行符的路径名,那么更改文件中的终止符并添加适当的选项是可行的方法。