user1296965
user1296965

Reputation: 409

ZSH for loop array variable issue

I'm working in , but I'm sure that instructions will also be helpful.

I need to have a for loop that goes through the values stored in the array lw and then launches a shell script, based on the name value stored in the array.

So far, this is what I've come up with:

$lw=('plugin1' 'plugin2' 'plugin3')

for i in $lw;
  do . ~/Library/Rogall/plugins/$lw[$i]/lw.prg end;
done

Running this gives me an error saying that it can't find ~/Library/Rogall/plugins//lw.prg. It appears as if it's ignoring my variable all together.

Any ideas where I've messed up?

Upvotes: 39

Views: 53978

Answers (4)

altimes
altimes

Reputation: 440

For others who end up here wrestling with shell scripts, arrays and spaces in filenames...... like my file list below;

$ ls *.meta
20160324 1850 - ABC - Clarke And Dawe.ts.meta
20160706 1515 - 9Gem - Agatha Christie's Poirot.ts.meta
20181213 0155 - 10 BOLD - Star Trek_ The Next Generation.ts.meta
20210424 1927 - ABCTV HD - The Durrells.ts.meta
20210501 1927 - ABCTV HD - The Durrells.ts.meta
20210818 1930 - SBS ONE HD - Tony Robinson's World By Rail.ts.meta

After a lot of searching and trying different approaches this worked out to be the least problematic and worked on MacOS 10.15

eval "list=( $(find . -name "*.ts" -exec echo \"{}\" \;) )"
for name in "${list[@]}"
do
res=`mediainfo --Output=''Video\;\%Width\%:%Height\%'' "$name"`
echo ${name} :: $res
sed -i .bak -e 5s/\;[[:digit:]]*:[[:digit:]]*// -e 5s/$/\;$res/ "$name.meta" 
done

Ignoring the internals of what I was trying to achieve, the critical aspects were using eval and wrapping double quotes around the filename in the echo within the find. (What was I doing? I was pulling the resolution out of Enigma2 PVR recordings and writing it into line 5 of the related meta data file)

Thanks to all those who posted their own knowledge on the various issues that shell scripting generates.

Upvotes: 1

user3310334
user3310334

Reputation:

I had a problem where a loop like this one

for i in (1 2 3 4); do echo $i; done

was repeatedly not working as I wanted. I would get errors like zsh: unknown file attribute: 1, or outputs like

1 2 3 4

no matter how I re-contorted it, instead of my desired

1
2
3
4

To get my desired behaviour I had to remove the in keyword from the loop definition

for i (1 2 3 4); do echo $i; done
1
2
3
4

Upvotes: 12

Jan Krüger
Jan Krüger

Reputation: 18530

It's actually much simpler than that:

lw=('plugin1' 'plugin2' 'plugin3')

for i in $lw; do
  . ~/Library/Rogall/plugins/$i/lw.prg end
done

In summary:

  • Assign to foo, not $foo (the shell would try to expand $foo and assign to whatever it expands to; typically not useful)
  • Use the loop variable directly; it contains the array value rather than the index

Upvotes: 69

William Pursell
William Pursell

Reputation: 212674

Why bother using the array? This can be done in portable sh very easily:

lw='plugin1 plugin2 plugin3'

for i in $lw;
  do . ~/Library/Rogall/plugins/$i/lw.prg end
done

Note that for this to work in zsh, you need to make zsh do the right thing with: set -o shwordsplit

Upvotes: 30

Related Questions