Here's a completely portable answer (to any Bourne-derived shell on pretty much any system that can run one of those), whereas all the other answers are at least a little non-portable, either rely on non-portable shell constructs or seq
, which is common but neither in POSIX
nor universal:
# start with a blank/clean "dirs" variable
dirs=
# iterate over the first digit
for i in 0 1 2
do
# ..and the second digit for each first digit
for j in 0 1 2 3 4 5 6 7 8 9
do
# add each digit combination to the dirs list
dirs=$dirs\ $i$j
# ..until we reach 23 - then we're done.
case $i$j in 23) break 2; esac
done
done
# finally make the directories
mkdir $dirs
Some notes:
Creating dirs initially ensures we don't accidentally use the value of an environment variable named dirs
, in case we inherit one.
We could actually skip building the $dirs
variable, and just call mkdir $i$j
. But this way performs better (one mkdir process launched instead of 24) and is just as portable (if by some chance there's really a system out there were mkdir
can only take one directory argument*, this is easy to adapt to call mkdir
for each $i$j
combination instead of building a $dirs
variable).
The lack of quoting everywhere is both intentional and correct. Substitutions do not need to be quoted inside variable assignments and in the first part of the case
statement: they don't undergo field splitting in those spots. And in the mkdir
line at the end, we're relying on the field splitting to separate the directory list into separate names/arguments for mkdir
.
* "Officially" MS-DOS and Windows has a mkdir
which only takes one directory name, but at least on Windows 7 it works with multiple directory names, plus any port of a Bourne-like shell to those systems that I know of comes with it's own mkdir
, and only weirdos like me would even think about that level of portability.