How to check if a file exists in a shell script

I'd like to write a shell script which checks if a certain file, archived_sensor_data.json, exists, and if so, deletes it. Following , I've tried the following:

[-e archived_sensor_data.json] && rm archived_sensor_data.json 

However, this throws an error

[-e: command not found 

when I try to run the resulting test_controller script using the ./test_controller command. What is wrong with the code?

3

6 Answers

You're missing a required space between the bracket and -e:

#!/bin/bash if [ -e x.txt ] then echo "ok" else echo "nok" fi 
3

Here is an alternative method using ls:

(ls x.txt && echo yes) || echo no 

If you want to hide any output from ls so you only see yes or no, redirect stdout and stderr to /dev/null:

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no 
2

The backdrop to my solution recommendation is the story of a friend who, well into the second week of his first job, wiped half a build-server clean. So the basic task is to figure out if a file exists, and if so, let's delete it. But there are a few treacherous rapids on this river:

  • Everything is a file.

  • Scripts have real power only if they solve general tasks

  • To be general, we use variables

  • We often use -f force in scripts to avoid manual intervention

  • And also love -r recursive to make sure we create, copy and destroy in a timely fashion.

Consider the following scenario:

We have the file we want to delete: filesexists.json

This filename is stored in a variable

<host>:~/Documents/thisfolderexists filevariable="filesexists.json" 

We also hava a path variable to make things really flexible

<host>:~/Documents/thisfolderexists pathtofile=".." <host>:~/Documents/thisfolderexists ls $pathtofile filesexists.json history20170728 SE-Data-API.pem thisfolderexists 

So let's see if -e does what it is supposed to. Does the files exist?

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $? 0 

It does. Magic.

However, what would happen, if the file variable got accidentally be evaluated to nuffin'

<host>:~/Documents/thisfolderexists filevariable="" <host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $? 0 

What? It is supposed to return with an error... And this is the beginning of the story how that entire folder got deleted by accident

An alternative could be to test specifically for what we understand to be a 'file'

<host>:~/Documents/thisfolderexists filevariable="filesexists.json" <host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $? 0 

So the file exists...

<host>:~/Documents/thisfolderexists filevariable="" <host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $? 1 

So this is not a file and maybe, we do not want to delete that entire directory

man test has the following to say:

-b FILE FILE exists and is block special -c FILE FILE exists and is character special -d FILE FILE exists and is a directory -e FILE FILE exists -f FILE FILE exists and is a regular file ... -h FILE FILE exists and is a symbolic link (same as -L) 

Internally, the rm command must test for file existence anyway,
so why add another test? Just issue

rm filename 

and it will be gone after that, whether it was there or not.
Use rm -f is you don't want any messages about non-existent files.

If you need to take some action if the file does NOT exist, then you must test for that yourself. Based on your example code, this is not the case in this instance.

4

If you're using a NFS, "test" is a better solution, because you can add a timeout to it, in case your NFS is down:

time timeout 3 test -f /nfs/my_nfs_is_currently_down real 0m3.004s <<== timeout is taken into account user 0m0.001s sys 0m0.004s echo $? 124 <= 124 means the timeout has been reached 

A "[ -e my_file ]" construct will freeze until the NFS is functional again:

if [ -e /nfs/my_nfs_is_currently_down ]; then echo "ok" else echo "ko" ; fi <no answer from the system, my session is "frozen"> 
2

You could also uses stat :

stat / File: / Size: 4096 Blocks: 8 IO Block: 4096 directory Device: fd01h/64769d Inode: 2 Links: 26 Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2009-01-01 02:00:00.000000000 +0200 Modify: 2009-01-01 02:00:00.000000000 +0200 Change: 2009-01-01 02:00:00.000000000 +0200 Birth: - 

On a path that doesn't exist, you will get:

stat /aaa stat: cannot stat '/aaa': No such file or directory 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like