DEV Community

Myoungjin Jeon
Myoungjin Jeon

Posted on

Fish Shell Function

My PATH has so duplicated paths

I was cleaning up my PATH environment value yesterday
and I found my path has so many duplicated paths inside.

My duplicated PATH env.

~> set -S PATH
$PATH: set in global scope, exported, a path variable with 27 elements
$PATH[1]: |/home/myoungjin/.local/share/go/bin|
$PATH[2]: |/home/myoungjin/.local/share/rakudo/share/perl6/site/bin|
$PATH[3]: |/home/myoungjin/.local/share/rakudo/bin|
$PATH[4]: |/home/myoungjin/.rakudo/install/share/perl6/site/bin|
$PATH[5]: |/home/myoungjin/.rakudo/install/bin|
$PATH[6]: |/home/myoungjin/.ghcup/bin|
$PATH[7]: |/home/myoungjin/.local/bin|
$PATH[8]: |/home/myoungjin/perl5/bin|
$PATH[9]: |/home/myoungjin/sbin|
$PATH[10]: |/home/myoungjin/bin|
$PATH[11]: |/home/myoungjin/perl5/bin|
$PATH[12]: |/home/myoungjin/bin|
$PATH[13]: |/home/myoungjin/.local/share/go/bin|
$PATH[14]: |/home/myoungjin/.local/share/rakudo/share/perl6/site/bin|
$PATH[15]: |/home/myoungjin/.local/share/rakudo/bin|
$PATH[16]: |/home/myoungjin/.rakudo/install/share/perl6/site/bin|
$PATH[17]: |/home/myoungjin/.rakudo/install/bin|
$PATH[18]: |/home/myoungjin/.ghcup/bin|
$PATH[19]: |/home/myoungjin/.local/bin|
$PATH[20]: |/home/myoungjin/perl5/bin|
$PATH[21]: |/home/myoungjin/sbin|
$PATH[22]: |/home/myoungjin/bin|
$PATH[23]: |/usr/local/bin|
$PATH[24]: |/usr/bin|
$PATH[25]: |/usr/bin/site_perl|
$PATH[26]: |/usr/bin/vendor_perl|
$PATH[27]: |/usr/bin/core_perl|
Enter fullscreen mode Exit fullscreen mode

Starting making block of code (function)

So I found that when I added some new path for my apps in new PATH, I hadn't check its possibility of existence already in there.

There are millions of way to check. A famous way maybe done
by external programme.

function elem_ -d 'find first value is in the list of rest values'
    # note: fish index start from 1
    for p in $argv[2..-1]; echo $p; end | grep -q $argv[1]
end
Enter fullscreen mode Exit fullscreen mode

But how about just using pure fish shell script by using basic
array that fish provides. so my first try was like:

function elem -d 'find first value is in the list of rest values'
    set found 0
    for arg in $argv[2..-1]
        if test $found -eq 0 && test $arg = $argv[1]
            set found 1
            break
        end
    end

    if test $found -eq 1
        true
    else
        false
    end
end


~> elem 1 1 2 3
~> echo $status
0
Enter fullscreen mode Exit fullscreen mode

Add A function in your fish shell permanently

now you can make a file which has file path of
~/.config/fish/functions/elem.fish

so that you can use it whenever you want to use it.

Now, we did make how to check, we could make append_to_path or prepend_to_path function like this.

~/.config/functions/fish/append_to_path.fish

function append_to_path -d 'append given path into PATH environment variable with checking '
    if ! elem $argv[1] $PATH
        set -x --append PATH $argv[1]
    end
end
Enter fullscreen mode Exit fullscreen mode

So, we can append a path safely now.

# middle of ~/.config/fish/config.fish
for p in ~/perl5/bin ~/.local/share/go/bin ~/.ghcup/bin \ 
        ~/.cabal/bin

    append_to_path $p
end
Enter fullscreen mode Exit fullscreen mode

Thank you for reading!

If you would like to know more about fish function
please visit my blog post.

Top comments (2)

Collapse
 
leandrorosa profile image
Leandro Rosa

Nice article :)
But I believe that there is a built-in function that does this: fish_add_path

fishshell.com/docs/current/cmds/fi...

"If a component already exists, it is not added again and stays in the same place unless the --move switch is given."

Collapse
 
jeongoon profile image
Myoungjin Jeon • Edited

oh, thank you!
It has been added since 1 year ago already.
github.com/fish-shell/fish-shell/b...

I think I lived in the past too long time.