How do I tell mkdir to try creating dir1, and if it already exists create dir2, etc, until it hits a name that doesn't exist?

6,938

Solution 1

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)

Solution 2

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))"

Solution 3

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.

Solution 4

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:
6,938
01AutoMonkey
Author by

01AutoMonkey

Updated on September 18, 2022

Comments

  • 01AutoMonkey
    01AutoMonkey almost 2 years

    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.

  • Thorbjørn Ravn Andersen
    Thorbjørn Ravn Andersen over 10 years
    Binary search on the number might be good enough.
  • Thorbjørn Ravn Andersen
    Thorbjørn Ravn Andersen over 10 years
    This is a good idea, but is not easy to parallize.
  • glenn jackman
    glenn jackman over 10 years
    Unless there are millions of directories, parallelization is definitely premature optimization.
  • JdeBP
    JdeBP over 10 years
    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.
  • Ruslan
    Ruslan over 10 years
    Why would you need printf here? Won't simple echo work?
  • Ruslan
    Ruslan over 10 years
    Also, I'd use dir[0-9]* instead of dir*.
  • Thorbjørn Ravn Andersen
    Thorbjørn Ravn Andersen over 10 years
    You misunderstand. I talk about whether the script is sensible to being run multiple times at once (multiple threads, multiple users etc) or not.
  • glenn jackman
    glenn jackman over 10 years
    @Ruslan, sort needs one filename per line. echo will just output the filenames space-separated. Note that dir[0-9]* will still match "dir1a". For just "dir followed by numbers" we can do: shopt -s extglob; printf "%s\n" dir+([0-9])