2

I'm running on a server where qstat gives me the IDs of running jobs (details not important). E.g., say I have three jobs running, 123, 124, 125, then

> qstat
123
124
125

Each job has a log file in logs/. I want to tail -F the log files of all jobs.

I attempted

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

but I get

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

for each job.


I'm running zsh, the same thing works in bash!

Apparently, there is no wild card expansion after $(...), could that be? How do I fix this for zsh?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
fabian789
  • 217

1 Answers1

4

Yes, doing filename expansion upon command substitution and other expansions is generally not wanted¹ and not done by default in zsh except in sh/ksh emulation (globsubst option).

While you could use ${~$(...)} to request the use of globsusbt for that particular command substitution (and by the way, you don't need the paste part, both space and newline are in the default value of $IFS), a much better way to do it with zsh would be:

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

Note that if any of those globs fail to match any file, the command will be aborted.

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

(where (N) activates nullglob for those globs) would avoid that but would run tail -F without argument if there was no file at all (see Why is nullglob not default?).

You could also make it:

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

¹ The fact that bash and other Bourne-like shells do it could be seen as a bug. That's one reason why you need to quote all your variables there, or why you need set -o noglob before using an unquoted $(...) when you only want the splitting part of that split+glob. All more modern shells that don't carry the Bourne shell baggage like rc, es or fish don't do it either.