atomic create file if not exists from bash script

You could create it under a randomly-generated name, then rename (mv -n random desired) it into place with the desired name. The rename will fail if the file already exists.

Like this:

#!/bin/bash

touch randomFileName
mv -n randomFileName lockFile

if [ -e randomFileName ] ; then
    echo "Failed to acquired lock"
else
    echo "Acquired lock"
fi

A 100% pure bash solution:

set -o noclobber
{ > file ; } &> /dev/null

This command creates a file named file if there's no existent file named file. If there's a file named file, then do nothing (but return a non-zero return code).

Pros wrt the touch command:

  • Doesn't update timestamp if file already existed
  • 100% bash builtin
  • Return code as expected: fail if file already existed or if file couldn't be created; success if file didn't exist and was created.

Cons:

  • need to set the noclobber option (but it's okay in a script, if you're careful with redirections, or unset it afterwards).

I guess this solution is really the bash counterpart of the open system call with O_CREAT | O_EXCL.


Here's a bash function using the mv -n trick:

function mkatomic() {
  f="$(mktemp)"
  mv -n "$f" "$1"
  if [ -e "$f" ]; then
    rm "$f"
    echo "ERROR: file exists:" "$1" >&2
    return 1
  fi
}

Examples:

$ mkatomic foo
$ wc -c foo
0 foo
$ mkatomic foo
ERROR: file exists: foo

Tags:

Linux

C

Bash