我正在一台服务器上运行,该服务器为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 包袱,例如rc
,es
或者fish
也不这样做。