Unix tip #1: advanced mkdir and brace expansion fun
If you don’t know all the ins and outs of the mkdir command, you are probably expending more effort than necessary. Imagine this fairly common use case:
You are in a folder and want to create one folder which has 3 sub folders. Let’s call the main folder Programming and its 3 sub folders Java, Python, and Scala. Visually this looks like
or rendered via tree:
Programming/ |-- Java |-- Python `-- Scala
A first pass at accomplishing this would be to create the Programming folder, and then the three individual folders underneath
$ mkdir Programming $ mkdir Programming/Java $ mkdir Programming/Python $ mkdir Programming/Scala
This certainly works, but it takes four commands.
Let’s see if we can’t do better. Delete those folders with the command
rm -rf Programming/
This will delete the programming folder and all subfolders underneath it (the r flag is for recursive, the f flag for forcing the removal of nonempty directories)
Like most unix commands, the mkdir command can take multiple arguments, separated by spaces. So the three separate commands to create Java, Python, and Scala can be put onto one line.
mkdir Programming; mkdir Programming/Java Programming/Python Programming/Scala
Note the ; separator between the two commands. We need to create the Programming folder before we can create the subfolders.
This is better but still too verbose. It would be nice to remove the mkdir Programming call; we’d like to be able to create an arbitrarily nested folder and have mkdir create all the parent folders automatically. Fortunately there is a way to do this: the -p flag of mkdir does exactly this.
-p Create intermediate directories as required. If this option is not specified, the full path prefix of each operand must already exist. On the other hand, with this option specified, no error will be reported if a directory given as an operand already exists. Intermediate directories are created with permission bits of rwxrwxrwx (0777) as modified by the current umask, plus write and search permission for the owner.
Thus we can change our command to
mkdir -p Programming/Java Programming/Python Programming/Scala
This is better but still not perfect; we’re repeating ourselves 3 times with the Programming call. Enter an absurdly useful Bash shell construct known as brace expansion.
echo {5,6,7} 5 6 7
The arguments within braces are treated as if they were space separated instead. That wouldn’t be terribly useful except that things immediately before the brace are repeated as well
echo hello{5,6,7} hello5 hello6 hello7
This brace expansion can be used anywhere, since the textual substitution happens before the arguments are passed into other processes. So, combining this with what we saw earlier, we can put Java, Python and Scala into a list and prepend it with Programming:
echo Programming/{Java,Python,Scala} Programming/Java Programming/Python Programming/Scala
That should look very familiar. Putting it in place of the earlier mkdir command we get the elegant one liner
mkdir -p Programming/{Java,Python,Scala}
Certain versions of bash also support numerical ranges within the brackets:
echo {1..10} 1 2 3 4 5 6 7 8 9 10
Conclusion:
I have shown you how to create all the parent directories using the mkdir command, and introduced you to the brace expansion macro of Bash. The latter is extremely powerful, and can be used to great effect within scripts.
Note: The arguments within the braces must have NO space between after or before the commas in order for the brace expansion to work.
[572][nicholasdunn: Desktop]$ echo {5, 6, 7} {5, 6, 7} [573][nicholasdunn: Desktop]$ echo {5,6,7} 5 6 7
Pretty cool!
I really wish I’d know this a long while ago.
Yeah, once I found out about the brace expansion, a whole new world of possibilities opened up.
The mkdir -p is pretty useful too, especially if you have to create a deeply nested folder structure. I didn’t mention it in the article but you can have more than one set of braces; {a,b,c}{d,e,f} yields ad ae af bd be bf cd ce cf
Thanks for the tip on brace expansion. I came here after seeing the term mentioned in the bash manpage with no further explanation! -ag
Thanks honey ;-!
Was searching (via https://duckduckgo.com) for the commands to create a dir and change immediately into it.
Add this one example it is very usefull;
mkdir -p {2009..2013}/{1..12}
another one:
mkdir -p archief/{client1,client2,client3}/{2015..2025}/{{jan,mar,may,july,aug,oct,dec}/{1..31},feb/{1.28},{apr,june,sept,nov}/{1..30}}
after creating the folder structure, a file (example.txt) will be created in each (day) subfolder
touch archief/{client1,client2,client3}/{2015..2025}/{{jan,mar,may,july,aug,oct,dec}/{1..31},feb/{1.28},{apr,june,sept,nov}/{1..30}}/example.txt
That’s really slick. I didn’t know you could do the nested braces.
Thanks for your explanation !