Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to create a directory with a number at the end, e.x. "dir1", and increment that number if the directory already exists until it hits a directory name that doesn't exist, and I need to do this in a single line in a Linux command line, something like:

mkdir --increment dir$

How would I go about doing that?

So far I've got this:

dir=output; n=0; mkdir -p $dir$n; if test -d $dir$n; then n=$((n+1)); echo $dir$n; fi

But it just echos the next dir name, I need it to recursively execute the command.

share|improve this question

5 Answers 5

up vote 23 down vote accepted

This is a trivial exercise in the use of while:

n=0
while ! mkdir dir$n
do
    n=$((n+1))
done

But of course it doesn't take much thought to realize that this trivial mechanism doesn't scale well.

So instead of reinventing the wheel and having to shave off all of the corners again, one creates unique temporary directories from a template slightly differently:

name=$(mktemp -d dirXXXXXXXXXXX)

share|improve this answer
    
Binary search on the number might be good enough. –  Thorbjørn Ravn Andersen Mar 3 at 11:53
    
There are quite a few corners to shave off from where you're starting in the wheel reinvention process, not the least of which are remembering the filesystem, considering security, and parallelization. –  JdeBP Mar 3 at 13:40

find the "biggest" dirname first, get the number and increment that:

last_dir=(printf "%s\n" dir* | sort -Vr | head -1)
num=$(last_dir#dir)
mkdir "dir$((num+1))"
share|improve this answer
    
This is a good idea, but is not easy to parallize. –  Thorbjørn Ravn Andersen Mar 3 at 11:54
    
Unless there are millions of directories, parallelization is definitely premature optimization. –  glenn jackman Mar 3 at 13:36
    
Why would you need printf here? Won't simple echo work? –  Ruslan Mar 3 at 14:01
    
Also, I'd use dir[0-9]* instead of dir*. –  Ruslan Mar 3 at 14:02
1  
You misunderstand. I talk about whether the script is sensible to being run multiple times at once (multiple threads, multiple users etc) or not. –  Thorbjørn Ravn Andersen Mar 3 at 14:04

If you just want to incrementally create directories that are listed in the correct order, may I instead recommend folders that are named based on the current date?

DATE=$(date +%F)
mkdir "dir-$DATE"

It will create directories with the names like dir-2014-03-02 (YYYY-MM-DD, so as to appear in alphabetical order).

If you create more than one directory per day, you can add the current time to the file name. See man date on how to tweak the output formatting of date.

share|improve this answer

Assuming your directories always start off at "dir1", and that there are no files named $dir* (iE they are all sequentially numbered directories), you can get away with this one liner -

mkdir ${dir}$(( `ls ${dir}* | wc -w` + 1 ))

This counts the number of files starting with $dir, then adds one to that number and creates a new file.

share|improve this answer

Addendum to the other answers: If you need the dirs to sort correctly by name, you may also want to pad the new dir number (NUM) with leading zeros to a fixed length.

The following could be condensed onto one line or embedded in one of the other solutions.

NUM="00"$NUM                  ## Left zero pad with fixed length - 1 zeros 
NUM=${NUM:((${#NUM} - 3)):3}  ## left trim to fixed length (3 in this case)

This assumes that NUM starts out at least 1 digit long and will not exceed the fixed length. Adjust accordingly to your requirements.

share|improve this answer

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.