Bash – How to check if a file can be created or truncated/overwritten in bash

basherror handlingfiles

The user calls my script with a file path that will be either be created or overwritten at some point in the script, like foo.sh file.txt or foo.sh dir/file.txt.

The create-or-overwrite behavior is much like the requirements for putting the file on the right side of the > output redirect operator, or passing it as an argument to tee (in fact, passing it as an argument to tee is exactly what I'm doing).

Before I get into the guts of the script, I want to make a reasonable check if the file can be created/overwritten, but not actually create it. This check doesn't have to be perfect, and yes I realize that the situation can change between the check and the point where the file is actually written – but here I'm OK with a best effort type solution so I can bail out early in the case that the file path is invalid.

Examples of reasons the file couldn't created:

  • the file contains a directory component, like dir/file.txt but the directory dir doesn't exist
  • the user doens't have write permissions in the specified directory (or the CWD if no directory was specified

Yes, I realize that checking permissions "up front" is not The UNIX Way™, rather I should just try the operation and ask forgiveness later. In my particular script however, this leads to a bad user experience and I can't change the responsible component.

Best Answer

The obvious test would be:

if touch /path/to/file; then
    : it can be created
fi

But it does actually create the file if it's not already there. We could clean up after ourselves:

if touch /path/to/file; then
    rm /path/to/file
fi

But this would remove a file that already existed, which you probably don't want.

We do, however, have a way around this:

if mkdir /path/to/file; then
    rmdir /path/to/file
fi

You can't have a directory with the same name as another object in that directory. I can't think of a situation in which you'd be able to create a directory but not create a file. After this test, your script would be free to create a conventional /path/to/file and do whatever it pleases with it.

Related Question