Bash 分割文件列表

Bash 分割文件列表

我的文件夹中有 200 个文件,例如:test_1_cfg.dattest_2_cfg.dat、.... 等等。我需要在 bash 脚本中包含前 40 个文件作为输入并运行一些进程,另一个脚本来读取接下来的 40 个文件并运行另一个进程。

所以我正在考虑一种方法来获得文件名列表,然后拆分该列表,但我不确定如何在 bash 中执行此操作。

任何想法?

答案1

方法#1 - 使用头尾

您可以使用该命令head从文件列表中提取前 40 个文件,如下所示:

$ head -40 input_files | xargs ...

要获得接下来的 40 个:

$ tail -n +41 input_file  | head -40 | xargs ...

...

$ tail -n +161 input_file | head -40 | xargs ...

您可以使用相同的技术继续沿着列表向下走,一次 40 个。

方法 2 - 使用 xargs

如果您碰巧将所有文件名都放在一个变量中,则可以xargs像这样使用将列表分解为 X 个元素的块。

例子

假设我的文件名为 1-200。所以我将它们加载到一个变量中,如下所示:

$ files=$(seq 200)

您可以看到此变量中的前几项:

$ echo $files  | head -c 20
1 2 3 4 5 6 7 8 9 10

现在我们用xargs它来划分:

$ xargs -n 40 <<<$files
1 2 3 4 5 6 7 8 9 10 ...
41 42 43 44 45 46 47 ...
81 82 83 84 85 86 87 ...
121 122 123 124 125 ...
141 142 143 144 145 ...
161 162 163 164 165 ...
181 182 183 184 185 ...

然后,您可以将上述命令传递给另一个命令,xargs然后该命令将运行您的程序:

$ xargs -n 40 <<<$files | xargs ...

如果无法从变量轻松访问文件列表的内容,您可以xargs通过文件给出列表:

$ xargs -n 40 <input_file
1 2 3 4 5 6 7 8 9 10 ...
41 42 43 44 45 46 47 ...
81 82 83 84 85 86 87 ...
121 122 123 124 125 ...
141 142 143 144 145 ...
161 162 163 164 165 ...
181 182 183 184 185 ...

方法 #3 - Bash 数组

假设您的文件名位于 Bash 数组中。我再次使用数字 1-200 的序列来表示我的文件名。

$ foo=( $(seq 200) )

您可以像这样查看数组的内容:

$ echo ${foo[@]}
1 2 3 4 5 ....

现在获取第一个 40:

$ echo "${foo[@]:0:40}"

第二个40等:

$ echo "${foo[@]:40:40}"
...
$ echo "${foo[@]:160:40}"

答案2

这是一个完美的食谱xargs

cat list_of_files | xargs -n 40 command

引用自man xargs

 -n number   Set the maximum number of arguments taken from standard input
             for each invocation of the utility.  An invocation of utility
             will use less than number standard input arguments if the
             number of bytes accumulated (see the -s option) exceeds the
             specified size or there are fewer than number arguments
             remaining for the last invocation of utility.  The current
             default value for number is 5000.

为了对每组执行不同的操作,您需要先获取相关行,然后再将其传递给xargs

 sed -n '1,40p' list_of_files | xargs command1
 sed -n '41,80p' list_of_files | xargs command2
 ...     

答案3

仅供参考,我喜欢xargs -n 40 <<<$files,但因为它每行有“40 个参数”,所以我做了

threads=10
xargs -n $((40/threads)) <<<$files

或者如果在数组中..

n=(1 2 3 4 5 6)
xargs -n $((${#n[@]}/threads))

while read -r input; do
  for item in $input; do
    <..stuff..>
  done &
done <<< $(for x in ${n[@]}; do echo $x; done | xargs -n $((${#n[@]}/threads)))
wait

相关内容