如何将文件列表作为 bash 变量传递给 zcat?

如何将文件列表作为 bash 变量传递给 zcat?

我正在尝试将单个输出流传递到zcatbash 管道中。让我们将其用作wc -l此示例的管道。

zcat -f /var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log | wc -l

实际上返回的是行数。

paths="/var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log"
zcat -f "${paths}" | wc -l

gzip: /var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log.gz: 没有这样的文件或目录

如何将所有这些文件合并到标准输出,以便我的管道只进行一次传递而无需中间文件?我尝试传递整个字符串结果.gz附加到变量,就好像这是单个参数一样

答案1

var=('first value' 'second value'...)列表使用中的语法进行分配bash

paths=(/var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log)
zcat -f -- "${paths[@]}" | wc -l

请注意, of$path包含一个空列表,zcat -f -- "${paths[@]}"将成为zcat -f --并且当未传递任何文件名参数时,zcat将读取其标准输入而不是根本不产生任何输出。

要解决这个问题,您可以这样做:

{ (( ${#paths[@]} == 0 )) || zcat -f -- "${paths[@]}"; } | wc -l

或者:

zcat -f -- </dev/null "${paths[@]}" | wc -l

如果您想/var/log/log*以相反的数字顺序连接文件,您宁愿使用 shell zsh,而bash不是执行以下操作:

zcat -f /var/log/log*(nOn) | wc -l

(这是ame 的numerical order(O反向大写)n)。

并且不需要上述的解决方法;如果没有匹配的文件,你会得到:

$ zcat -f /var/log/log*(nOn) | wc -l
zsh: no matches found: /var/log/log*(nOn)
0

答案2

不加引号的变量将使 shell 执行分词和文件名生成。由于您只想要第一个效果,因此可以禁用后者:

paths="/var/log/log.3.gz /var/log/log.2.gz /var/log/log.1.gz /var/log/log"
(
  set -f
  zcat -f $paths | wc -l   # variable is unquoted
)

我添加了括号,因此该设置仅在该子 shell 的生命周期内有效。

显然,允许 shell 进行分词意味着如果任何路径名包含空格,它就会中断。

相关内容