3

A process will be writing to a set of directories, one for each hour using date +%H notation, so 00, 01, 02... 22, 23. I'm wanting to keep the leading 0 on single digit hours to keep sorted listings tidy.

I=00; until [ $I -gt 23 ]; do mkdir $I; let I=I+1; done

Has predictable effects of not keeping a leading 0 before the single digits. I could just go and make them by hand, but feel there should be a way to do this. Any ideas?

4 Answers 4

12
mkdir $(seq -w 00 23)
13
mkdir {0{0..9},{10..23}}

Or in Bash 4:

 mkdir {00..23}
3
  • 1
    +1 for not spawning a subprocess. Nov 11, 2009 at 16:10
  • +1 , from my IRC hang out: "seq(1) is a highly nonstandard external command used to count to 10 in silly Linux howtos. Use one of these instead: for x in {1..10} (bash3.x) or for ((x=1; x<=10; x++)) (bash 2.04+) or i=1; while [ $i -le 10 ]; do ...; i=$(($i+1)); done (ksh/POSIX)" Nov 11, 2009 at 18:46
  • At least in Bash, you can do ((i++)) to increment a counter in a while loop (or elsewhere). Also, if you use double parentheses you can use <= and leave off the $: i=1; while ((i<=10)); do echo $i; ((i++)); done. Nov 11, 2009 at 19:16
6
for i in `seq -w 00 23`;do mkdir $i;done
0
3

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.

1
  • (I am aware the question is tagged with bash, but I believe this answer is sufficiently likely to be useful to system admins, etc, who may stumble upon this answer.)
    – mtraceur
    Mar 14, 2016 at 6:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .