Cleaning $HOME on macOS

Apple computers ship with a custom operating system - macOS, which has a few annoying features. Among the annoyances a special place has to be reserved for the inability to remove or rename the folders located in $HOME. Here I describe my way of dealing with this problem.

Hiding default folders

On the web countless macOS users are looking for answers to the same question: “How can I get rid of ‘Desktop’, ‘Documents’, ‘Downloads’, ‘Library’, ‘Movies’, ‘Music’, ‘Pictures’, and ‘Public’ folders?” Multiple suggestions are provided as possible solutions. You can: replace the folders with files(1); hide the folders from ‘Finder’ and make them inaccessible(2); or simply learn to live with them, as the system will recreate those folders by itself anyway(3).

I decided to hide. But, when working in the command line, hiding these folders from Finder is not enough. Below are three settings that, while not covering all corner cases, go a long way.

  1. hide from Finder by adding a hidden flag

    chflags hidden ~/Desktop ~/Documents ~/Downloads ~/Library
    chflags hidden ~/Movies ~/Music ~/Pictures ~/Public
  2. hide from ls by creating an alias in .bashrc

    alias ls='ls -I Desktop -I Documents -I Downloads -I Library\
                 -I Movies -I Music -I Pictures -I Public'
  3. hide from tab completion by setting a special bash FIGNORE(4) variable.

    export FIGNORE=Desktop:Documents:Downloads:Library:Movies:Music:Pictures:Public

That is it, the folders should mostly be out of view. And if for whatever reason we need to temporary see them again a simple \ls would bypass the alias and provide us the full list.

Creating a new hierarchy

With the folders out of view we can now move onto creating our own home hierarchy. This part mostly depends on the needs of the user. But I would like to offer one piece of advice: make sure your folders start with unique lowercase letters. This will allow you to auto-complete folder names after typing a single character and offer extra protection against invoking a command on one of those default hidden folders, that start with upper case letters.

In my case the new hierarchy looks like this:

├── base
│   ├─── bin
│   ├─── etc
│   ├─── src
│   └─── var
├── desk
├── file
│   ├─── articles
│   ├─── books
│   ├─── documents
│   ├─── essays
│   ├─── photos
│   └─── videos
└── work
    ├─── active_project_one
    ├─── active_project_two
    └─── zzz
         ├─── inactive_project_one
         ├─── inactive_project_two
         ├─── inactive_project_three
         ├─── inactive_project_four
         └─── ...

'base' is a substitute for '.local'.
'desk' takes the place of the 'Desktop' and 'Downloads'.
'file' is an aggregate of 'Documents', 'Music', 'Pictures', and 'Movies'.
'work' stores various active and completed projects.

Linking Downloads and Desktop

There is one detail remaining: macOS has a useful 'Desktop' and now its hidden from us. On top of that some third party applications put various acquired data into the 'Downloads' folder. Hence, we want to see the contents of those folders within our new file hierarchy. We achieve this with symbolic links.

  1. make 'Desktop' be a symbolic link for our new folder 'desk'

    sudo rm -rf Desktop
    ln -s desk Desktop
  2. make 'Downloads' be a symbolic link for 'Desktop'

    sudo rm -rf Downloads
    ln -s Desktop Downloads

And now whenever a file is put into the, now hidden, 'Downloads' or 'Desktop' folders, it will be placed in our 'desk' instead. Moreover, since 'Desktop' is a link to 'desk', whatever is put into the 'desk' directory will be visible on the actual desktop on a screen.

The result

$ ls ~/
base desk file work

$ cd ~/D<tab>
$ cd ~/D

$ cd ~/d<tab>
$ cd ~/desk


Getting rid of default macOS home directories is hard. Hiding, instead of trying to delete, seems like an easier and safer solution. The tricks presented in this article, while not being 100% effective, go along way. I’ve been using this approach for a few years without accidentally seeing any reminder of those folders during this whole time.

  1. Answer 1 on  ↩︎
  2. Answer 2 on  ↩︎
  3. Answer 3 on  ↩︎
  4. Bash variable documentation on  ↩︎