Americas

  • United States
sandra_henrystocker
Unix Dweeb

24 ways to check the status of files using if commands on Linux

How-To
Aug 23, 20228 mins
Linux

The Linux if command can help find types, permissions, and content of files, among many other things.

filing cabinet files records stokkete shutterstock
Credit: Stokkete / Shutterstock

There are a lot more ways to check files using if commands than many of us realize. Although this information is included in the bash man page, that man page has thousands of lines and you could easily find yourself paging down more than 100 times to reach it.

This post, provides information on each option and examples for some of the most useful ones.

Checking if a file exists

One of the most commonly used tests for checking on files is if [ -f filename ]. This test will result in true if the file exists and is a regular file—not a directory or a symbolic link. You might use it like this:

$ if [ -f myfile.txt ]; then
>   echo myfile.txt exists
> else
>   touch myfile.txt
> fi
myfile.txt exists

The command above would create the file using the touch command if it doesn’t already exist. The following command would only tell you if the file is or isn’t a regular file:

$ if [ -f /home/shs ]; then
>   echo file exists
> else
>   echo file is not a regular file
> fi
file is not a regular file

If you want to know whether a file exists regardless of what kind of file it is, you can use the -a or the -e test.

$ if [ -e symlink ]; then
>   echo file exists
> else
>   echo no such file
> fi
file exists

Checking if a file is a directory

Using -d will tell you if a file is a directory.

$ if [ -d /home/shs ]; then
>   echo directory
> else
>   echo not a directory
> fi
directory

Reversing the effect of if tests

You can reverse the effects of an if test by preceding the test with a ! (not) sign. To test if a file has content, you could use a command like this one:

$ if [ -s emptyfile ]; then
>   echo has content
> else
>   echo empty
> fi

To change the command above to test whether the file is empty, do this:

$ if [ ! -s emptyfile ]; then
>   echo empty
> else
>   echo has content
> fi

This of -s as “some content” and ! -s as “no content”.

The ! can be used with any of the if tests. Here are a few examples:

if [ ! -d file ]      

Checking file permissions

Other especially useful tests can tell you if you can read a file, write to a file or execute a file.

$ if [ -r ~/bin/loop ]; then
>   echo readable
> fi
readable

$ if [ -w ~/bin/loop ]; then
>   echo writable
> fi
writable

$ if [ -x ~/bin/loop ]; then
>   echo executable
> fi
executable

Note that these tests only check your access rights, not anyone else’s and that the files tested above are all in the bin directory in the user’s home directory (~/bin).

You can also check whether a file is a character-special file, if its SGID (set group ID) bit is set and if its SUID (set user ID) bit is set. The chmod command sets the bits being tested in the second and third examples.

$ if [ -c /dev/tty11 ]; then
>   echo character-special file
> fi
character-special file

$ chmod 7755 yn
$ if [ -g yn ]; then
>   echo SGID set
> fi
SGID set

$ if [ -u yn ]; then
>   echo SUID set
> fi
SUID set

Checking if a file was recently modified

The -N checks whether a file’s content was modified since the last time it was read. The echo command below adds a line, so the second test result is the opposite of the first.

$ if [ -N testfile ]; then
>   echo file has been modified
> else
>   echo file not modified
> fi
file not modified

$ echo “——-“ >> testfile
$
$ if [ -N testfile ]; then
>   echo file has been modified 
> else
>   echo file not modified
> fi
file has been modified

Comparing file ages

You can use if tests to determine if one file has been changed more recently than another. The -nt test means “newer than”.

$ if [ file1 -nt file2 ]; then
>   echo file1 is newer
> else
>   echo file2 is newer
> fi
file2 is newer

Using -ot (older than) in place of -nt has the opposite effect.

All if commands for checking the status of files

Here is a list of all the if tests that check the status of files. Just remember that any can be reversed with a ! symbol (e.g., if [ ! file1 -ot file2 ]).

  • if [ -a FILE ] — True if FILE exists
  • if [ -b FILE ] — True if FILE exists and is a block-special file
  • if [ -c FILE ] — True if FILE exists and is a character-special file
  • if [ -d FILE ] — True if FILE exists and is a directory
  • if [ -e FILE ] — True if FILE exists
  • if [ -f FILE ] — True if FILE exists and is a regular file
  • if [ -g FILE ] — True if FILE exists and its SGID bit is set
  • if [ -h FILE ] — True if FILE exists and is a symbolic link
  • if [ -k FILE ] — True if FILE exists and its sticky bit is set
  • if [ -p FILE ] — True if FILE exists and is a named pipe (FIFO)
  • if [ -r FILE ] — True if FILE exists and is readable
  • if [ -s FILE ] — True if FILE exists and has a size greater than zero
  • if [ -t FD ] — True if file descriptor FD is open and refers to a terminal
  • if [ -u FILE ] — True if FILE exists and its SUID (set user ID) bit is set
  • if [ -w FILE ] — True if FILE exists and is writable
  • if [ -x FILE ] — True if FILE exists and is executable
  • if [ -O FILE ] — True if FILE exists and is owned by the effective user ID
  • if [ -G FILE ] — True if FILE exists and is owned by the effective group ID
  • if [ -L FILE ] — True if FILE exists and is a symbolic link
  • if [ -N FILE ] — True if FILE exists and has been modified since it was last read
  • if [ -S FILE ] — True if FILE exists and is a socket
  • if [ FILE1 -nt FILE2 ] — True if FILE1 has been changed more recently than FILE2 or if FILE1 exists and FILE2 does not
  • if [ FILE1 -ot FILE2 ] — True if FILE1 is older than FILE2 or if FILE2 exists and FILE1 does not
  • if [ FILE1 -ef FILE2 ] — True if FILE1 and FILE2 refer to the same device and inode numbers

if test result
[ -a FILE ] True if FILE exists
[ -b FILE ] True if FILE exists and is a block-special file
[ -c FILE ] True if FILE exists and is a character-special file
[ -d FILE ] True if FILE exists and is a directory
[ -e FILE ] True if FILE exists
[ -f FILE ] True if FILE exists and is a regular file
[ -g FILE ] True if FILE exists and its SGID bit is set
[ -h FILE ] True if FILE exists and is a symbolic link
[ -k FILE ] True if FILE exists and its sticky bit is set
[ -p FILE ] True if FILE exists and is a named pipe (FIFO)
[ -r FILE ] True if FILE exists and is readable
[ -s FILE ] True if FILE exists and has a size greater than zero
[ -t FD ] True if file descriptor FD is open and refers to a terminal
[ -u FILE ] True if FILE exists and its SUID (set user ID) bit is set
[ -w FILE ] True if FILE exists and is writable
[ -x FILE ] True if FILE exists and is executable
[ -O FILE ] True if FILE exists and is owned by the effective user ID
[ -G FILE ] True if FILE exists and is owned by the effective group ID
[ -L FILE ] True if FILE exists and is a symbolic link
[ -N FILE ] True if FILE exists and has been modified since it was last read
[ -S FILE ] True if FILE exists and is a socket
[ FILE1 -nt FILE2 ] True if FILE1 has been changed more recently than FILE2 or if FILE1 exists and FILE2 does not
[ FILE1 -ot FILE2 ] True if FILE1 is older than FILE2 or if FILE2 exists and FILE1 does not
[ FILE1 -ef FILE2 ] True if FILE1 and FILE2 refer to the same device and inode numbers

—>

Wrap-Up

There are a lot of ways to check and verify files on the command line or within scripts. Some of these options can help ensure that your scripts check files before trying to use them or avoid overwriting them if they already exist. These tests often play an important role when using scripts to automate your work.

sandra_henrystocker
Unix Dweeb

Sandra Henry-Stocker has been administering Unix systems for more than 30 years. She describes herself as "USL" (Unix as a second language) but remembers enough English to write books and buy groceries. She lives in the mountains in Virginia where, when not working with or writing about Unix, she's chasing the bears away from her bird feeders.

The opinions expressed in this blog are those of Sandra Henry-Stocker and do not necessarily represent those of IDG Communications, Inc., its parent, subsidiary or affiliated companies.