我有很多文件,命名约定如下:
file1_d
, file2_d
, file3_d
, ...,fileN_d
我想将第一个k
文件提供到脚本中作为输入,然后将以下k
文件作为第二批提供,依此类推。有没有一种简单的方法可以在 shell 脚本中执行此操作,例如使用数组?
答案1
我假设您想要多次执行该脚本,并且想要批量提供文件作为脚本的命令行参数,每次运行脚本时一次一批。 (您的要求的另一种解释是脚本从标准输入读取文件,并且您希望k
一次向其提供文件的串联。下面的代码只需要进行少量更改即可实现这种解释。)
在bash
shell 中,您可以使用分块提供给脚本的数组。
要创建数组,我们可以这样做
files=( file*_d )
这将扩展通配模式file*_d
并将结果名称按字典顺序放入数组中。如果您需要按数字顺序排列文件名,并且数字不是以零填充,那么使用大括号扩展会更容易:
files=( file{1..N}_d )
...其中N
是最大数量(实际数量,不是变量,因为bash
不理解大括号扩展范围中的变量)。
在zsh
shell 中,您可以使用以下命令创建数组
files=( file<->_d )
...按数字顺序排列它们。下面的代码适用于 和zsh
shell bash
。
然后您可以像这样循环调用脚本:
k=10
while [ "${#files[@]}" -gt 0 ]; do
./myscript "${files[@]:0:k}"
files=( "${files[@]:k}" )
done
这将./myscript
调用数组k
的第一个整体files
,然后从数组中删除这些条目。它会一直持续到数组为空为止。
答案2
在 中zsh
,您可以使用zargs
:
autoload zargs
zargs -l ${k?} -- file<->_d(n) -- myscript
使用 bash 和 GNU 实用程序,您可以执行类似的操作:
xargs -r0n"${k?}" -a <(
shopt -s failglob extglob
pattern='file+([0123456789])_d' IFS=
printf '%s\0' $pattern | sort -zV) myscript
globn
限定符或sort -V
确保文件名按数字排序,以便file10_d
在后面file9_d
file1_d
例如而不是中间file2_d
。
如果您想运行其中一些,GNUzargs
和 GNUxargs
都有一个选项-P
myscript
选项。
答案3
您可以使用 GNU Parallel 来并行执行批处理。
printf '%s\n' file*_d | parallel -j 2 -N "$k" ./myscript
如果您的脚本不从 stdin 读取,而是需要一个参数,您可以使用:::
像这样传递它:
parallel -j 2 -N "$k" ./myscript ::: file*_d
-j
指定同时运行的作业数(默认为可用核心数)以及-N
指定您的情况下的参数限制或批量大小。因此,如果您有-j 2 -N 10
脚本,系统将给出每个文件 10 个文件的列表,并且将随时运行两个不同的作业。一旦一个完成,另一个就会开始,直到所有文件被消耗。
如果你不想运行并行作业,你可以通过-j 1
答案4
简单-使用xargs
:
$ # Let's create 100 files with your naming convention
$ for i in {1..100} ; do touch $(printf "file%03d_d" $i) ; done
$ # Now let's process them in groups of 4 with this script:
$ cat /path/to/some/script.sh
#!/bin/bash
echo called with "$@"
$ ls | LC_ALL=C sort | xargs -n 4 /path/to/some/script.sh
called with file001_d file002_d file003_d file004_d
called with file005_d file006_d file007_d file008_d
called with file009_d file010_d file011_d file012_d
...
called with file093_d file094_d file095_d file096_d
called with file097_d file098_d file099_d file100_d
使用 C 语言环境前缀sort
可能是我的偏执 - 使用任何语言环境/排序选项按照您希望处理文件的顺序对文件进行排序。
如果您想知道,这确实适用于不能完美划分数据集的数字:
$ ls | LC_ALL=C sort | xargs -n 3 /path/to/some/script.sh
...
called with file091_d file092_d file093_d
called with file094_d file095_d file096_d
called with file097_d file098_d file099_d
called with file100_d