DEV Community

Hannah Balenda
Hannah Balenda

Posted on

Beginner’s Guide to Executables and Where To Store Them

Maybe I should be more embarrassed to admit this, but I always kind of just pray to god when I install CLIs, and it usually works. But I recently go a new computer, so I’ve had to install a lot of things, and as I’m following the install instructions for Sublime 3’s CLI for OS X, I read this:

The first task is to make a symlink to subl. Assuming you've placed Sublime Text in the Applications folder, and that you have a ~/bin directory in your path, you can run:

ln -s "/Applications/Sublime" ~/bin/subl

Now I’d like to say I’m not guilty of copy and pasting things I don’t fully understand, but sometimes there’s only so much space in this brain. It looks like we’re making a symlink from the subl file that comes packaged with Sublime 3 to ~/bin, where we’ll be able to execute it from the command line, which feels familiar enough. So I mkdir bin and copy/paste their command and get command not found.

And then I’m like, yeah, maybe I don't really know what's going on here. Also don't I sometimes put this stuff in /usr/local/bin?

So I did some research and took a look at the file system hierarchy manual page by running man hier, and boy howdy, we’ve got some confusing duplicate directory names:

The modern OS X file system:

  • / Root directory of the filesystem
  • /bin User utilities fundamental to both single-user and multi-user environments
  • /dev Device files
  • /etc System configuration files
  • /mach_kernel Kernel executable (the operating system loaded into memory at boot time)
  • /sbin System programs and administration utilities fundamental to both single-user and multi-user environments
  • /tmp Temporary files
  • /usr System-wide, read-only files. All installed software goes here.
    • /bin Common utilities, programming tools, and applications provided by the OS.
    • /lib Archive libraries provided by the OS.
    • /local System-wide, read-only files, but only the ones provided by the user i.e. you.
    • /bin Executables
    • /lib Libraries
  • /var

So, executables and libraries provided by the OS are going to be in /bin, /sbin, /usr/bin, and /usr/lib. Anything in addition to that we want to install system-wide and that should be available for all users should go in /usr/local, and executables (like the sublime CLI I was trying symlink) should go in /usr/local/bin.

So, I could edit the original command to install the Sublime CLI to this:

sudo ln -s "/Applications/Sublime" /usr/local/bin/subl

But if we take a closer look at the original Sublime command, they're pointing to ~/bin, which is shorthand for /Users/<username>/bin. It's a common convention to store executables that only need to be available to the current user here, and better practice to avoid using sudo and installing things at the root when we don't need to. But in order to use it, I need to add ~/bin (or, $HOME/bin) to my path variable (which is a list of directories where executables are stored) by editing my .bash_profile to include:

export PATH="$HOME/bin:$PATH"

Now running original Sublime command will work as intended. And voila! Now I can subl to my heart’s content, and even better, I understand a little more about what’s going on in my /usr directory.

Side note: For some history into why there’s a /bin and /lib in both / and /usr, I recommend checking out this post by Rob Landley from 2010. Spoiler alert, it’s a holdover from working around limited disk space, and it isn’t a reason anymore! Explanations for the continued existence of this split have been repeatedly made in retrospect! If that doesn’t make you feel better about yourself as a developer, I don’t know what will.

Top comments (4)

moopet profile image
Ben Sinclair

I think there's a mistake in your first example - it looks like you skipped ahead a step, because the error message and command refer to different paths:

ln -s "/Applications/Sublime" ~/bin/subl
-bash: /usr/local/bin/subl: No such file or directory

If it's just something for you, not something for all users, then putting it into ~/bin like Sublime suggests is probably a better idea. You'll usually have to add $HOME/bin to your PATH, but that's a one-off change, and it'll set you up for knowing how to install things on environments where you're not the owner, like shared hosting or generally any foreign system.

If you're downloading something then being able to install it without having root is good because in my opinion, waaaay too many tutorials and whatnot expect you to copy-paste commands starting with sudo whether they need root permissions or not, and I've seen a lot of people just end up using it as a hammer to fix every bent nail.

Also worth checking out is the install command, which handles a lot of this for you but copies the files instead of linking them. Too many symlinks in /usr/local/bin means that after a while, as your machine gets older, you're likely to run into some broken ones from when you thought you'd tidy up all those install files into an old_programs directory.

hbalenda profile image
Hannah Balenda • Edited

Ah, you're right, it should've been "command not found". And right about adding ~/bin to my $PATH, I hadn't done that yet setting up the new computer, and never really understood why I should do that, but now I get it! Thank you so much, I'm updating the post to reflect this.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.