Creating folder hierarchies with mkdir

There have been a few posts in the BBS recently about creating pre-defined folder hierarchies. The most obvious method, for an AppleScripter, would be a recursive process involving the Finder. But the same thing can be achieved with a single Unix ‘mkdir’ command. This is incredibly fast and is (for a Unix command) quite easy to understand.

If you have a folder “a” on your desktop, the following will create a folder “b” inside it:

set desktopPath to POSIX path of (path to desktop)
set mkdirStr to "mkdir " & desktopPath & "a/b/"
--> "mkdir /Users/username/Desktop/a/b/"

do shell script mkdirStr

If there’s no folder “a” then the script will error. But with the addition of a parameter ‘-p’, the script will create both “a” and “b” if necessary. In fact, it will create any folder in the supplied path that doesn’t already exist.

set desktopPath to POSIX path of (path to desktop)
set mkdirStr to "mkdir -p " & desktopPath & "a/b/c/d/e/"
--> "mkdir -p /Users/username/Desktop/a/b/c/d/e/"

do shell script mkdirStr

The ‘man’ page for ‘mkdir’ doesn’t reveal that, besides being able to create folders to any reasonable depth, the command can also handle width, and can create multiple sibling folders in the same directory. The following creates folders “b”, “c”, “d”, and “e” in the top level of folder “a” (and creates “a” too if necessary).

set desktopPath to POSIX path of (path to desktop)
set mkdirStr to "mkdir -p " & desktopPath & "a/{b,c,d,e}/"
--> "mkdir -p /Users/username/Desktop/a/{b,c,d,e}/"

do shell script mkdirStr

Although the brace syntax looks like an AppleScript list, there should be no spaces after the commas. There’s another trick you can do with braces here. If the left brace comes immediately after a slash or a comma, as above, then the text between the commas represents the names of the subfolders to be created at that level. But if the left brace comes immediately after some text, then the stuff between the commas is suffixed to that text in the names of all the created folders. (Or, if you prefer, the text is prefixed to the stuff between the commas.) This can save some typing if you want siblings’ names to begin with the same text:

set desktopPath to POSIX path of (path to desktop)

-- (Note the single quotes round the space to mark it as part of the name.)
set mkdirStr to "mkdir -p " & desktopPath & "a/Chapter' '{1,2,3,4}/"
--> "mkdir -p /Users/username/Desktop/a/Chapter' '{1,2,3,4}/"

do shell script mkdirStr
--> Folders "Chapter 1", "Chapter 2", "Chapter 3", and "Chapter 4" are created in folder "a"

Similarly, if the right brace is followed immediately by text, that text is suffixed to the stuff between the commas. All this cleverness is very versatile. It can be nested and combined in several ways to define an entire hierarchy, and can provide hours of experimental fun:

-- (Other lines omitted for brevity.)
set mkdirStr to "mkdir -p " & desktopPath & "a/Chapter' '{1,2,3,4}c/"
--> In folder "a": folders "Chapter 1c", "Chapter 2c", "Chapter 3c", and "Chapter 4c".

set mkdirStr to "mkdir -p " & desktopPath & "a/Chapter' '{1,2,3,4}/c/"
--> In folder "a": folders "Chapter 1", "Chapter 2", etc., each containing a folder "c".

set mkdirStr to "mkdir -p " & desktopPath & "a/Chapter' '{1,2/c,3,4}/"
--> In folder "a": folders "Chapter 1", "Chapter 2", etc., only "Chapter 2" containing a folder "c".

set mkdirStr to "mkdir -p " & desktopPath & "a/{Chapter' '{1,2/c,3,4},Index}/"
--> In folder "a": four "Chapter" folders and an "Index" folder. "Chapter 2" contains a folder "c".

There’s an upper limit to the length of the mkdir string, but you’re unlikely to hit it. A hierarchy-duplication script I wrote last year can happily recreate the 895 folders in my Library folder with one ‘mkdir’ call. It takes a few seconds for the script to collect the information and think about the string, but once that’s done, the entire duplicate hierarchy is created almost instantaneously. If I were more au fait with Unix, the infomation gathering might be quicker too. :slight_smile:

Nice write-up :slight_smile:

That’s because mkdir isn’t responsible for this feature. It’s actually the shell doing it. (It can therefore be used with other commands besides mkdir.) Since do shell script calls the bash shell, you’ll find a discussion of this feature in man bash. Skip down to “Brace Expansion.”

Hi, Rainy Day.

Thanks for the compliment and for the information about brace expansion.

I’ve not got much into shell scripting myself, as most of the things I need to do are performed much faster and more understandably by AppleScript. ‘mkdir’ is an honourable exception because even a shell script call is faster than several commands to the Finder. Since ‘man’ pages are (to me) utterly opaque ” and often interminably long ” reading them isn’t one of my main hobbies! So what little I know about brace expansion comes from experimentation after seeing what someone else had done with ‘mkdir’. Your explanation clears up why it’s not mentioned in the ‘man’ page. Thanks again. :slight_smile:

I’ve just made a PDF of ‘man bash’, using Adam and Bruce’s script. It’s sixty pages!

(I’ve also made a couple of edits in the examples in my original post to try and make it clearer what they’re supposed to do.)

Yeah, shell scripting sure can be obtuse at times, and the documentation often elusive. But it can be very powerful (and concise) too, as your write-up so very well illustrates. I find the combination of AppleScript and shell scripting to be a gestalt where the whole is truly greater than the sum of its parts. Shell scripting is like a magical portal to an alternate reality.

The shell expansion stuff is definitely worth understanding. So are shell conditionals and loops. For anything other than simple file and directory manipulation, i find the shell almost always easier to use than AppleScripting the Finder (you must be careful about manipulating files with resource forks in a pre-Tiger shell, however!) Certain “simple” tasks are sometimes easier in the shell, such as checking to see if a file exists (see man test). YMMV.

Other useful tools to be aware of are grep, sort and uniq. Simple one-line perl commands can be extremely useful for modifying files (or as an in-line editor), but finding good examples can be difficult (most perl examples are complicated programs, and there is a labyrinth of a couple dozen or so perl manuals). sed can do much the same and is easier to find examples for, but sometimes it just falls short (whereas perl can usually do the task with ease). And awk can be quite useful too. If you know how to use these tools, and understand how to use Unix pipes to connect them together, you can do some amazing stuff (which often executes very quickly). The equivalent AppleScript code, if it can be done at all, would be very complicated, and quite slow. The shell environment is just an incredible resource for an AppleScripter to have in his toolbox.

When working with shell scripts, Apple’s “do shell script in AppleScript” (aka TN2065) is essential reading. It also helps to sort out some of the quoting hassles in calling shell scripts from AppleScript (which in my opinion is the biggest impediment).

I think Adam and Bruce’s script is pretty interesting. It might be interesting to merge it with a shell function for use from the Terminal.