通配符扩展 zsh

通配符扩展 zsh

我正在一台服务器上运行,该服务器为qstat我提供了正在运行的作业的 ID(细节并不重要)。例如,假设我正在运行三个作业,123, 124, 125,那么

> qstat
123
124
125

每个作业都有一个日志文件logs/。我想要tail -F所有作业的日志文件。

我尝试过

tail -F $(qstat | awk -v P=logs '{ print P"/*"$1 }' | paste -sd " ")

但我得到

tail: cannot open logs/*123 for reading: No such file or directory

对于每项工作。


我正在跑步zsh,同样的事情也适用bash

显然,$(...) 后没有通配符扩展,可能是这样吗?我该如何修复这个问题zsh

答案1

是的,通常不需要在命令替换和其他扩展时进行文件名扩展,并且默认情况下 zsh 中不会执行文件名扩展,除了 sh/ksh 模拟(globsubst选项)。

虽然您可以${~$(...)}请求使用 globsusbt 来进行特定的命令替换(顺便说一下,您不需要该paste部分,空格和换行符都在默认值中$IFS),但使用 zsh 更好的方法将会:

ids=($(qstat))
tail -F logs/*${^ids}

请注意,如果这些 glob 中的任何一个无法匹配任何文件,该命令将被中止。

tail -F logs/*${^ids}(N)

(其中(N)激活空球tail -F对于那些全局变量)将避免这种情况,但如果根本没有文件,则将在没有参数的情况下运行(请参阅为什么 nullglob 不是默认值?)。

你也可以做到:

logs=(logs/*${^$(qstat)}(N))
(($#logs)) && tail -F $logs

1 和其他类似 Bourne 的 shell 这样做的事实bash可以被视为一个错误。这就是原因之一你需要引用所有变量那里,或者为什么当您只想要 split+glob 的拆分部分时需要set -o noglob在使用不带引号的之前。$(...)所有更现代的 shell 都不携带 Bourne shell 包袱,例如rces或者fish也不这样做。

相关内容