The Robservatory

Robservations on everything…

 

Quickly create a nested folder structure via Terminal

Have you ever needed to create an empty folder structure with many levels of repetitively-named folders? This doesn't happen a lot, obviously, but if you try using Finder for this task, you'll quickly discover it's really tedious. But a quick trip to Terminal makes the task very fast, and it's not overly complicated.

Let's say you need a folder structure to handle reports that you'll be receiving weekly, but need to keep track of over both quarters and years. One way to handle that would be with a folder structure like this:

(Hopefully obviously, the same structure repeats within each separate year's folder.) Creating that many multi-leveled folders in Finder would be time consuming and tedious. But in Terminal, you can create the entire structure with just one command:

mkdir -p 202{0..5}/qtr{1..4}/week{1..13}

That command takes under a second on my iMac to create the entire directory structure (over 330 folders). Zoom! So how does this work?

Note: Before you play around with this, I suggest creating a test folder on your Desktop (or wherever), and then, in Terminal, execute cd ~/Desktop/testfolder before you do anything else—that way, the folder structures will be within one folder, and easily deleted if something doesn't go quite right.

In the shell (both bash in pre-Catalina, and zsh in Catalina), the curly braces have a number of uses. Here they're being used to generate sequences—you can use numbers or letters, and as long as they're separated by two dots, the shell will attempt to fill in the missing values—you can even reverse the order. Here are a few examples:

  • {a..z} The letters a to z
  • {p..d} The letters p back to d
  • {A..C}{0..3} This sequence creates every combination of A to C and 0 to 3—i.e. A0, A1, A2, A3, B0, B1, etc.

You can test any of these with the echo command, which will output the result of the expansion:

$ echo {A..C}{0..3}
A0 A1 A2 A3 B0 B1 B2 B3 C0 C1 C2 C3

Braces are not reserved for mkdir; they're a shell feature, so you can use them in many places.

For example, touch demofile_{1..10000}.txt will quickly (as in only a few seconds) create 10,000 empty dummy files…in case you need a big batch to test with Name Mangler, for example.

But back to creating folders…the key to making this work is the -p flag on the mkdir, which tells mkdir to create any non-existing directories on the defined path. With that flag set, the shell expands the sequences and creates all the missing folders.

If you're adventurous, and don't mind using bash over zsh in Catalina, you can install a newer version of bash that supports more sequence options, most notably a skip feature:

$ echo {a..z..2}
a c e g i k m o q s u w y

The ..2 bit tells the expansion to only output every second letter. To make this work, though, you must be on a newer bash shell than ships with macOS. This how-to explains the steps involved in installing and switching to a newer version of bash.

You can do a lot more with curly braces; this guide provides many more examples. (Some of those examples take advantage of the above-described skip feature.)

The command line may be ancient and mostly supplanted by GUIs, but there are times when it really is the easiest and fastest way to get some things done.

5 Comments

Add a Comment
  1. I love it.... now if you could just tell me how to remove all the fonts and documents in languages I don't speak, that the OS won't let me remove. ;-D

  2. "The ..2 bit tells the expansion to only output every second letter. To make this work, though, you must be on a newer bash shell than ships with macOS"

    It also works in the version of zsh in Catalina, which is now the default shell for new accounts. Time to migrate!

    (Not that I'm one to speak - I still use tcsh as my shell on one of my computers)

    1. Matthew:

      Are you sure about that? I have two Catalina Macs here, one on 10.15.4 and one still on 10.15.3, and both return this when I try to use the modified form:

      % echo {a..z..2}
      {a..z..2}

      They're running zsh 5.7.1. On my 10.14.6 machine with Apple-provided bash, I get the same output. But with the newer bash, I get the expected:

      $ echo {a..z..2}
      a c e g i k m o q s u w y

      Can you confirm which version of zsh you're using, and that it actually does work? If so, there's something really weird going on.

      -rob.

  3. I love it. Works a treat on my catalina

    Now, to find a way to copy all of the image files from a particular folder on an SD card (out of the camera) to a heirarchy on my pictures folder of (year) / (month ) / day.

    1. It's probably feasible, though much will depend on whether you need to use the EXIF date or if you can use the date info from the file on disk. I looked briefly for a Mac app to do this, but didn't find one. I did find this, which might be useful as a starting point:

      https://apple.stackexchange.com/questions/143639/app-to-organize-my-photos-into-folders-by-date

      And if you do need the EXIF date, you can install exiftool, which is most easily done via Homebrew (brew install exiftool).

      Good luck! :)

      -rob.

Leave a Reply

Your email address will not be published. Required fields are marked *

The Robservatory © 2020 • Privacy Policy Built from the Frontier theme