Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
up vote 12 down vote accepted
mkdir $(seq -w 00 23)
share|improve this answer
mkdir {0{0..9},{10..23}}

Or in Bash 4:

 mkdir {00..23}
share|improve this answer
1  
+1 for not spawning a subprocess. – James Sneeringer Nov 11 '09 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)" – Kyle Brandt Nov 11 '09 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. – Dennis Williamson Nov 11 '09 at 19:16
for i in `seq -w 00 23`;do mkdir $i;done
share|improve this answer

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.

share|improve this answer
    
(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 at 6:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.