How to execute certain commands if the file does NOT exist?

I am trying to get the equivalent of the following C code in shell scripts.

if(!exist) { command; command; } else { command; command; } 

What I'm trying to more accurately in this shell script is to check if there is a file and then create it.

I'm also sorry if this is a duplicate of another question, but I really didn't know how to look for it.

+8
file shell
source share
4 answers

You can use this:

 if [!  -e "$ file"];  then
        touch file
 else
         ...
 fi
+14
source share

Checking for a file is a very common task. To find relevant questions, use the search bar (top right). I got a lot of results with the terms "bash script"

In any case, you need either the built-in test or its semantic equivalent [ ] :

 [ ! -e your_file ] && >your_file 

or

 test ! -e your_file && >your_file 

which first test that your_file does not exist ( ! ) exists ( -e ) and creates it if this is the case.

For more information about the various tests you can run (except for -e ), you can enter:

 help -m test | less 
+16
source share
 if [ ! -e "$path" ] then touch -- "$path" fi 

The simplest version is just touch -- "$path" - it creates a file if it does not exist, and simply updates the access and modification time if it exists. a double dash ( -- ) ensures that you can create a file even if it starts with a dash and quotes around $path needed.

+7
source share

Do not do this, it not only depends on the conditions of the race, but also [ -e /path/file ] checks if you can do stat(2) in the file, so it will return false for various reasons, not only because the file does not can exist.

An example is a symbolic link to a file that does not exist, or a file in a directory in which you do not have permission to search.

It is much better to use the right flags for the open(2) system call here, i.e. O_CREAT|O_EXCL . Thus, open() crashes if the file no longer exists, unless you need to check several millions of processor clocks earlier.

With a bourne-like shell:

 if (set -C && : > "$file") 2> /dev/null; then print '%s\n' "$file has been created else print '%s\n' "It hasn't, possibly because it was already there" fi 

( set -C - enable the O_EXCL flag).

Also, why do you want to create an empty file? Most likely you want to save something in this file. Then just do it:

 set -C { echo blah other-commands that-generate-the-content } > "$file" 

Then this group of commands is executed only if file no longer exists (and it could be created).

If you want to check for a file, write it at a minimum:

 [ -e "$file" ] || [ -L "$file" ] 

or

 ls -d -- "$file" > /dev/null 2>&1 

if you are wondering if this is a symbolic link. This will still return false if the file exists, but you do not have the right to check it.


Now, if you need a longer and more historical answer about testing file existence:

Initially, the test command (on Unix v7, where it first appeared) did not have the -e (and -h / -L ) or -a unary option) .

The way to check for the existence of a file was ls . ls (with -d ) lists the file and reports an error (and returns false exit status) if it cannot search for the file for one reason or another. Unix did not initially have symbolic links, but when they were introduced, ls was changed to make lstat(2) in the file instead of stat(2) . That is, in the case of symlink ls returns information about the symlink file, not the file in the path pointed to by the symlink.

The test (aka [ ) option for testing the file’s “existence” was first introduced into the Korn test builtin shell . It was -a , not -e . -a for accessible (I believe), which is a more accurate term than the existing one.

I do not know when or what -e entered, possibly POSIX. POSIX says that -e was chosen over -a to avoid possible confusion with the binary operator -a (for and).

In either case, both -a and -e try stat(2) in the file, not lstat(2) . I.e:

 [ -e "$file" ] 

equivalent to:

 ls -Ld -- "$file" > /dev/null 2>&1 

So, strictly speaking, it returns true, if during the test it was possible to find the path after resolving symbolic links, and if stat(2) fails, the cause of the failure is ignored.

stat can fail if the file does not exist ( ENOENT ), that is, if the file does not exist or exists, but is a symbolic link to a file that does not exist, but also for a large number of other reasons. Looking at possible error codes, stat(2) gives a few ideas:

  • EACCESS : during path resolution (and this can be any component of the path and the path of any symbolic link) you do not have permission to search for one component of the directory (note that you can still access the file through another path).
  • ELOOP : ELOOP to resolve path due to too many symbolic links allowed for access.
  • ENOTDIR . For example, to /etc/passwd/foo or a symbolic link to it.
+7
source share

All Articles