Jesse Jesse - 1 year ago 46
Bash Question

Changing Values of Lists In Loop With Fish Shell Script

I am trying to iterate over a fish shell list and change the values of the elements saving those new values into that list.

The original list is populated like this:

set -l dockApplications (ls $HOME/.config/plank/dock1/launchers/)

This works and produces a list like this:

emacsclient.dockitem firefox.dockitem monodevelop.dockitem Thunar.dockitem

Now I want to iterate over it and change the string "dockitem" to "desktop".

I have tried a for loop but I do not appear to be using it correctly:

for application in $dockApplications
echo $application
set application (string replace 'dockitem' 'desktop' $application )
echo $application
echo "==========="

This echos the before and after the string operation and I produce the correct string. but when I do something like
echo $dockApplications
after the for loop. I get the list of strings with the "dockitem" extension.

I have also tried setting the
variable differently like:

set -l dockApplications (string replace 'dockitem' 'desktop' (ls $HOME/.config/plank/$dockdir/launchers/))

But that seems to return the same list of strings with the "dockitem" extension.

I think I am fundamentally misunderstanding either how variables are assigned or how the scope of them is handled here.

I have never fully wrapped my head around shell scripting. I can read it and get what is going on but when it comes to implementing it I hit a few road blocks when I try to achieve something in a way that I would in a different language. But I realize the power of shell scripting and would like to get better at it. So any pointers on how to do this in a fish shell idiomatic way are greatly appreciated.

Answer Source

I would iterate over the indices of the list so you can update in place:

set apps (printf "%s\n" ./launchers/*.dockitem)
for i in (seq (count $apps))
    set apps[$i] (string replace "dockitem" "desktop" $apps[$i])
printf "%s\n" $apps

This also works without a loop:

set apps (string replace dockitem desktop (printf "%s\n" ./launchers/*.dockitem))
printf "%s\n" $apps

If I recall, fish splits the output of a command substitution on newlines when saving to an array