Search code examples
shellshzsh

How to remove the need of "./" in every shell script in MacOS?


I'm studying shellscript and I know that there is a way to skip "./" when you need to execute a shellscript. For example: after I made a script like this:

echo "hello world!"

I use the command "chmod +X" to make it executable. But to execute it on my terminal I need to type:

./helloworld.sh

I know that theres is a way to skip this "./" if you're using bash. You go to .bashrc and write in the end of the script "PATH=PATH:." But since I'm using MacOS, which use zsh, I tried to type "PATH=PATH:." in the end of my .zshrc but this didn't work. Then I would like to know if there is a way to remove the need of "./" for every shellscript that I need to run.

Thank you people

P.S.: I have brew and ohmyzsh installed in my machine


Solution

  • What's Wrong with Your Code

    The reason your example doesn't work is because PATH is a variable, and you need to expand it by prefixing it with the dollar sign to access its value, e.g. PATH=$PATH:. rather than just PATH=PATH:.. However, there are some other considerations too.

    Prepending, Appending, and Exporting PATH

    It's generally not recommended to treat your current working directory as part of your PATH for security reasons, but you can do it in any Bourne-like shell by prepending or appending . (which means any current working directory) to your PATH. Depending on where you call it and how you've initialized your shell, you may also need to export the PATH variable to your environment.

    Some examples include:

    # find the named executable in the current working directory first
    export PATH=".:$PATH"
    
    # find the named executable in the current working directory
    # only if it isn't found elsewhere in your PATH
    export PATH="$PATH:."
    
    # append only the working directory you're currently in when you
    # update the PATH variable, rather than *any* current working 
    # directory, to your PATH
    export PATH="$PATH:$PWD"
    

    Note that it's also generally a good idea to quote your variables, since spaces or other characters may cause problems when unquoted. For example, PATH=/tmp/foo bar:$PATH will either not work at all or not work as expected. So, wrap it up for safety (with quotes)!

    Use Direnv for Project-Based PATH Changes

    You might also consider using a utility like direnv that would enable you to add the current working directory to your PATH when you enter known-safe directories, and remove it from the PATH when leaving the directory. This is commonly used for development projects, including shell scripting ones.

    For example, you could create the following ~/dev/foo/.envrc file that would only prepend the current working directory when in ~/dev/foo, and remove it again when you move above the current .envrc in your filesystem:

    # ~/dev/foo/.envrc
    #
    # prepend "$HOME/dev/foo:$HOME/dev/foo/bin" to your 
    # existing PATH when entering your project directory,
    # and remove it from your PATH when you exit from the
    # project
    
    PATH_add "$PWD/bin"
    PATH_add "$PWD"
    

    Because direnv uses whitelisting and ensures that your items are prepended to PATH, it's often a safer and less error-prone way to manage project-specific modifications to your PATH or other environment variables.

    Use "$HOME/bin" to Consolidate Scripts

    Another option is to create a directory for shell scripts in your home directory, and add that to your PATH. Then, any script placed there will be accessible from anywhere on your filesystem. For example:

    # add this line to .profile, .zprofile, .zshrc, or
    # whatever login script your particular terminal calls;
    # on macOS, this should usually be .zprofile, but YMMV
    export PATH="$HOME/bin:$PATH"
    
    # make a ~/bin directory and place your
    # executables there
    mkdir -p ~/bin
    cp helloworld.sh ~/bin/
    

    Assuming the shell scripts in your bin directory already have their executable bit set (e.g. chmod 755 ~/bin/*sh), you can run any shell script in that directory from anywhere on your filesystem.