我有这三个文本文件:
#1.txt
hey stackoverflow
#2.txt
hey stackexchange
#3.txt
hello world
我使用此命令列出我的目录中的最后 3 个文件,然后列出cat
它们,然后将 3 个文件的所有输出保存到一个文件 ( all.txt
)
命令 :
ls -alth *txt | head -3 | xargs -n1 cat
我如何将输出重定向到文件?
答案1
使用-l
(对于长列表)选项ls
在这里没有意义,因为您只需要文件名(与-h
(用于报告大小的 GNU 扩展相同)人类格式)随之而来)。
使用 的xargs
默认分割方式ls
也是不正确的,因为这会破坏包含空格、换行符、引号、反斜杠的文件名...
使用该-a
选项也是毫无意义的,因为 shell 是通过扩展此处的 glob 来计算文件列表的*txt
,而不是ls
,并且默认情况下 glob 扩展不包括隐藏文件。
你想要(在最近的 GNU 系统和 GNU shell (bash) 上):
shopt -s extglob
ls -Ltd --zero -- !(all.)txt | head -zn3 | xargs -r0 cat -- > all.txt
(dotglob
如果您希望考虑隐藏文件,还可以设置该选项)。
添加:
- 选项
-L
,以便ls
对于符号链接类型的文件,考虑符号链接目标的修改时间 -d
因为如果其中一些文件的类型为目录,您不想ls
列出它们的内容。--zero
//处理以 NUL 分隔的记录,NUL 是唯一不能出现在文件路径中的字符-z
。-0
!(all.)txt
而不是*txt
确保all.txt
不包含在列表中,这可能会导致无限循环填满磁盘。-r
选项以xargs
避免cat
在未找到文件时运行。--
标记选项的结尾,因此以或开头的文件名-
不会被视为选项。ls
cat
或者在任何系统上使用 zsh 而不是 bash:
set -o extendedglob
cat -- (^all.)txt(-.om[1,3]) > all.txt
在哪里:
^x
zsh 与 ksh 等效!(x)
(bash 通过其选项支持 ksh 扩展 glob 运算符的子集extglob
)-
相当于-L
.
限制于常规的文件(或常规文件的符号链接),不包括目录、fifo、设备...om
相当于-t
按修改时间排序。[1,3]
比如head -zn3
对前 3 个的限制。- 如果 glob 与任何文件都不匹配,则不会运行该命令并返回错误(与上面的 bash 命令相反,
all.txt
不会创建/截断)。
如果您希望考虑隐藏文件,请添加D
全局限定符( cat -- (^all.)txt(D-.om[1,3]) > all.txt
)