Content for Bash config
~/.bashrc
or ZSH config~/.zshrc
See my full Shell config file on GitHub.
OS flags
For any values in configs or aliases which are OS-specific, I found it useful to determine the OS with logic once-off and then reuse the flags.
IS_MAC=false
IS_LINUX=false
case "$(uname -s)" in
Darwin*)
IS_MAC=true
;;
Linux*)
IS_LINUX=true
;;
esac
That lets me then use the variable to perform OS-specific behavior. Here I add a Brew-installed Ruby gems path to the PATH
value, just for macOS.
if [[ "$IS_MAC" == 'true' ]]; then
export PATH="/usr/local/opt/ruby/bin:$PATH"
fi
Setting PATH the smart way
Part of the standard setup of packages like Ruby, Go and Node is to add a directory to your shell PATH
variable so that executables can be found.
If I want to check the directory exists first, I could do this:
if [ -d '/usr/local/opt/ruby/bin' ];
export PATH="/usr/local/opt/ruby/bin:$PATH"
fi
But I got tired of having that long syntax. So I made a function to do that, which I call like this:
prepend_path() {
if [ -d "$1" ]; then
export PATH="$1:$PATH"
fi
}
Usage:
# Ruby gems
prepend_path /usr/local/opt/ruby/bin
# Go packages.
# Traditional path is '/usr/local/go/bin' or '/usr/bin'.
# I created ~/.local to use that rather.
prepend_path ~/.local/go/bin
Executing local packages
When working on Node projects, you normally have to run a script like this in the shell:
$ ./node_modules/.bin/eslint
I'd rather just run this:
$ eslint
To get that behavior, I decided to add ./node_modules/.bin
to my PATH
variable.
prepend_path_always() {
export PATH="$1:$PATH"
}
prepend_path_always './node_modules/.bin'
Note that the values in PATH
are read from left to right, so you must make sure your local packages are read before any global packages. In case you have say eslint
installed locally and globally.
View the PATH
Here is what my PATH
value looks like.
$ split_path
/home/michael/.local/go/bin
/home/michael/.deno/bin
./node_modules/.bin
/home/michael/.local/bin
...
Note that the PATH
value normally looks like this with colon separators, making it hard to read.
/home/michael/.local/go/bin:/home/michael/.deno/bin:...
So I created an alias called split_path
which makes that more human-readable.
More about aliases in the next post in this series...
Top comments (7)
Thank you, interesting post!
But I think it is better to run the binary from node_modules like this:
Thanks for the tip. Npx is nice for scaffolding create apps but I didn't know it works for local packages.
According to this post I can just do a command without run.
blog.scottlogic.com/2018/04/05/npx...
Do you know if it respects the arguments?
Like if I wanted to run
Can I do that with npx? Like
Yes, you can)
Example:
run hexo version
run hexo version --debug
Thanks
Also my alias approach only works from the root. Does npx run from git root when run from anywhere?
I tried different options to learn how it works.
package.json located in /srv/projects/awesome-project/frontend/web/
gulp located in /srv/projects/awesome-project/frontend/web/node_modules/gulp/bin/
Run npx gulp --tasks
1) on /srv/projects/awesome-project/frontend/web/
2) on /srv/projects/awesome-project/frontend
Of course it doesn't work.
3) on /srv/projects/awesome-project/frontend/web/js
4) on /srv/projects/awesome-project/frontend/web/js/dist
Result - npx searches for the node_modules directory in the parent directories and tries to run the binary from there.
Neat