ARG!! Where do I put my executable???
Asking your distro’s opinion… $PATH contains a :
deliminated string of each directory that’s checked for executables and the directory names reveal if they’re managed and who they’re intended for.
Keep in mind every distro/system can be different though the terminology is often shared, this example is for Fedora:
# Try it:
$ echo $PATH
/home/ulfnic/.local/bin:/home/ulfnic/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
# Easier to read:
$ echo $PATH | tr ':' '\n'
# Or
$ echo $PATH | sed 's/:/\n/g'
/home/ulfnic/.local/bin
/home/ulfnic/bin
/usr/local/bin
/usr/bin
/usr/local/sbin
/usr/sbin
If I attempt to run xcalc
(the calculator 99.99% of Linux users are surprised to learn they have installed), the system will check the current directory, then those 6 directories from top to bottom till it finds xcalc
and runs it.
Where is xcalc
?
$ which xcalc
/usr/bin/xcalc
Should I uninstall xcalc
?
That’s a philiosophical question beyond the scope of this guide.
Terminology
Everyone describes these directories a bit differently but this is my practical summary:
-
local
is for files that aren’t ordinarily managed by the system (with things like dnf
or apt
). It’s a safe place for files to not be overwritten during standard installations and updates.
It’s commonly refered to as the place for “local” or “unique” files but syncing them against a public/private repo is just as valid a use case.
-
bin
is short for binary but all executables are welcome.
-
sbin
is like bin
but intended for the superuser only.
-
usr
is for all users.
-
home
is for specific users.
Breaking it down
/home/ulfnic/.local/bin ← I’m a custom executable intended for Ulfnic
/home/ulfnic/bin ← I’m a managed executable intended for Ulfnic
/usr/local/bin ← I’m a custom executable intended for everyone
/usr/bin ← I’m a managed executable intended for everyone
/usr/local/sbin ← I’m a custom executable intended for the superuser
/usr/sbin ← I’m a managed executable intended for the superuser
File & folder permissions ultimately determine who has access to what, for example if I chmod +x
instead of chmod u+x
a file in my user folder, all users will be able to execute it but the above is a decent guide to what these folders are generally intended for.
Where should I put my executable?
For a specific user: /home/$USER/.local/bin
For all users: /usr/local/bin
For superuser: /usr/local/sbin
BONUS: Making a shim
Because /local/bin
directories are checked prior to their /bin
equivalents it makes it easy to run a script first that then runs the program being asked for.
Example:
$ which nano # Make sure you know where the nano binary is first.
/usr/bin/nano
$ sudo touch /usr/local/bin/nano # Make a file named nano in /usr/local/bin/ so it's found first and run instead of the real nano.
$ sudo nano /usr/local/bin/nano # Edit
# Paste the following:
#!/usr/bin/env sh
echo "vim empowers users by teaching them lots of useful key"
echo "commands found in other terminal applications!"
echo ""
read -r -p "Are you sure you only want to learn nano? [y/N] " Res
case "$Res" in
[yY][eE][sS]|[yY])
# Respect the user's decision, Linux is about choice.
# Make sure to use nano's direct path gathered from `which nano` or this script will loop.
# Appending "$@" includes all the arguments so `nano myfile.txt` will still work.
/usr/bin/nano "$@"
;;
*)
# Check if vim is installed.
if $( -z which vim 2>/dev/null); then
echo
echo "Your distro is afraid even the GPL won't protect"
echo "them from the liability of users getting stuck in VIM!"
echo "You need to install it at your own risk."
else
echo
echo "Godspeed."
sleep 1
echo "Wait! Esc :q!"
sleep 1
vim "$@" # Transcend the user.
fi
;;
esac
# Save & exit (Ctrl + x)
$ sudo chmod +x /usr/local/bin/nano # Make it executable to all users
# The terminal session may need to be refreshed to see the change
$ exec bash
# Test the shim
$ nano
# Remove the shim in compliance with HR
$ sudo rm /usr/local/bin/nano