在目录中我有一定数量的文件。这可能是 53 个 txt 文件,但我也可能有 123 个文件。这些文件有各种随机名称,但都有文件句柄.txt
我可以使用 ls 获取所有文件的列表,并将其放入变量中。
list_of_txt_files=$(ls *.txt)
但我想将列表分成多个单独的列表,每个列表只有 10 个元素 - 即一个包含 53 个 txt 文件的文件夹,应该给我 6 个列表。这是包含 10 个文件名的 5 个列表,以及包含 3 个文件名的第 6 个列表,而我的目录中包含 123 个 txt 文件的示例应为我提供包含 10 个文件名的 12 个列表,以及仅包含 3 个文件名的第 13 个列表。
以我的 53 个 txt 文件为例:列出编号。 1 将保留第一个文件直到第十个文件,并列出 no。 2 将保存第十一个文件到第二十个文件,依此类推。我将我的问题从列表中的第 i 个元素命名为第 j 个元素,因为我想其他人可能想要以不同的方式分解列表。也许从目录中的第一个文件到第 100 个文件。
最终目标是能够在 for do 循环中使用这些列表,并使用 cat 命令,将每个列表的 10 个文件的内容写出到每组 10 个文件中的一个文件 - 即在我的示例中,有 53 个文件一个目录,这会给我 6 个文件。其中前 5 个文件包含 50 个原始 txt 文件的内容,第 6 个文件包含最后剩余 3 个 txt 文件的内容。
我考虑过使用 head 或 tail 命令,但无法完全弄清楚如何指定这两个命令的范围。
答案1
在一个外壳上数组, 使用它们。用 Bash 说:
$ touch {01..53}
$ files=(*)
$ echo "${files[@]:0:10}"
01 02 03 04 05 06 07 08 09 10
$ for ((i = 0 ; i < ${#files[@]} ; i += 10 )) ; do
echo "${files[@]:i:10}" ;
# or
# cat "${files[@]:i:10}" > set-$(( i / 10 ))
done
01 02 03 04 05 06 07 08 09 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53
这子串扩展(数组切片)"${files[@]:i:10}"
扩展为单词列表,而不是单个字符串,因此您可以对其进行循环:
for f in "${files[@]:i:10}" ; do
somecmd "$f"
done
不do files=$(ls *.txt)
,ls
在那里完全是多余的,无论如何,shell 都会评估通配符。通常,您只需将通配符模式保存到变量 ( pat=*.txt
) 并在需要时使用它(不带引号),或者如果您想将其扩展为实际文件名,请echo *.txt
使用ls
.对于处理文件名列表,如果您不限于普通的 POSIX shell,那么数组会更好。
至于用head
and分割列表tail
,您需要执行类似| head -20 | tail -10
获取第 11 行到第 20 行的操作。或者使用 sed: | sed -n 11,20p
。
答案2
使用任何类似 Bourne 的 shell(但 Bourne shell 无法通过 访问位置元素$9
),您可以执行以下操作:
set -- *.txt
while [ "$#" -gt 0 ]; do
something with "$1" ${2+"$2"} ${3+"$3"}... ${10+"${10}"}
[ "$#" -gt 10 ] || break
shift 10
done
xargs
使用支持进程替换的GNU和 shell:
xargs -n10 -r0a <(printf '%s\0' *.txt) something with
和zsh
:
files=(*.txt(N))
while (($#files)) {
something with $files[1,10]
files[1,10]=()
}
或者:
autoload -U zargs
xargs -l10 -- *.txt -- something with
zsh
另请注意,您可以在 的 glob中使用范围:
something with *.txt([1,10])