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?
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.
01AutoMonkey
Updated on September 18, 2022Comments
-
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 over 10 yearsBinary search on the number might be good enough.
-
Thorbjørn Ravn Andersen over 10 yearsThis is a good idea, but is not easy to parallize.
-
glenn jackman over 10 yearsUnless there are millions of directories, parallelization is definitely premature optimization.
-
JdeBP over 10 yearsThere 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 over 10 yearsWhy would you need
printf
here? Won't simpleecho
work? -
Ruslan over 10 yearsAlso, I'd use
dir[0-9]*
instead ofdir*
. -
Thorbjørn Ravn Andersen over 10 yearsYou 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 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])