How do I use zsh to pipe results from one command to another (while in a loop)?
macOS 10.14.6
zsh 5.8
jq 1.6
I have a situation where I have a bunch of .vital
files, which are JSON files in disguise. I want to extract one piece of information from each file, and I have worked out that after installing jq using brew install jq
, I can run, for example...
jq '.author' Analog_Bass__Lead.vital;
This gives me...
"maniclout"
which is the correct author for that item.
What I would like to do is to run this command over all my .vital
files, about 30 of them, in a for
loop.
I can list the files okay using...
for f in $(ls *.vital);
do
echo $f
done;
The problem comes when I try to construct a loop that would give the following...
Analog_Bass__Lead.vital "maniclout"
Blackhole_Dimension.vital "Cobranix"
and so on...
This my latest attempt (please, don't laugh!)...
for f in $(ls *.vital);
do
echo $f;
echo -n $f | jq ‘.author’
done;
As you can see, I'm trying to print the filename, followed by, on the same line, hence the -n
, and I'm trying to pipe the filename into the jq
command.
The results are fairly disastrous!
ANALOG_PAD_-_6.vital
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
‘.author’
jq: 1 compile error
Analog_Bass__Lead.vital
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
‘.author’
jq: 1 compile error
Atomosphere_Lead.vital
jq: error: syntax error, unexpected INVALID_CHARACTER, expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
‘.author’
jq: 1 compile error
Can anyone see what I am doing wrong?
Do not parse/interpret the output of ls
, too many things can go wrong. A simple way to accomplish your goal would be
for f in *.vital; do
echo -n "$f: "
jq '.author' "$f"
done
which might still fail if there are directories matching the pattern for instance. You can overcome this by using
for f in *.vital; do
[[ -f "$f" ]] || continue
echo -n "$f: "
jq '.author' "$f"
done
You can also go the full way and run
find . -maxdepth 1 -type f -name '*.vital' \
-exec sh -c 'echo -n "$1"; jq ".author" "$1"' _ {} \;
(see http://mywiki.wooledge.org/UsingFind#Complex_actions for how this works)
You could use find to get a list of .vital
files and then pipe that to jq
:
find *.vital | xargs jq '.author'