11

I want a Bash one-liner that atomically creates a file if it doesn't exist. That means essentially "if file doesn't exist, create it" but ensuring that no one else manages to create the file in the small space between doing the if and creating the file.

2

4 Answers 4

8

Stealing an answer from various comments and links to [SO]. It seems there is a POSIX compliant method that doesn't involve mkdir as I mentioned in my original answer below

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

This redirect to file returns 0 or fails and returns non-zero if the file already exists.


Original answer

You'll have to use mkdir - that's atomic, either the directory gets created and you can continue or it doesn't created so you take appropriate action.

Of course, mkdir doesn't create a file but once you know you have exclusive access to the directory then you can make the file you want in it.

As to a one liner - I'll leave that up to you. Personally I'd write it over a few lines, as that'll be more maintainable.

5
  • But noclobber from stackoverflow.com/q/13828544/1207760 is more what OP wants.
    – Law29
    May 1, 2016 at 15:50
  • Noclobber is, in general, a good answer. But it doesn't work for ksh88.
    – jrw32982
    May 3, 2016 at 20:44
  • 1
    @JohnWiersba but the question is about bash.
    – womble
    May 25, 2016 at 1:58
  • @womble yes but the answer mentions POSIX which someone might take to mean that the answer applies to other shells. Ksh88 is still the standard shell on some servers.
    – jrw32982
    Jun 3, 2016 at 15:25
  • Does this technique also work for bash in standard (non-posix) mode?
    – Binarus
    Nov 17, 2020 at 9:39
1

Try this one. The ln provides the test-and-set functionality.

touch lock.$$.tmp
if ln lock.$$.tmp lock.dat 2>/dev/null
then
    echo "File is mine"
else
    echo "Test and set failed"
fi
rm -f lock.$$.tmp
0

Is it file or directory? If file, you can use simple command touch - if file exists, it just modify last access time. If file doesn't exists, is created.

0

If you don't care about the filename, you can delegate this task to a utility, for example mktemp

Create a temporary file or directory, safely, and print its name.
TEMPLATE must contain at least 3 consecutive `X's in last component.
If TEMPLATE is not spec‐ified, use tmp.XXXXXXXXXX, and --tmpdir is 
implied.  Files are created u+rw, and directories u+rwx, minus umask
restrictions.

Invocation:

filename=$(mktemp)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .