371

I have a file called diff.txt. I want to check whether it is empty.

I wrote a bash script something like below, but I couldn't get it work.

if [ -s diff.txt ]
then
        touch empty.txt
        rm full.txt
else
        touch full.txt
        rm empty.txt
fi
5
  • 50
    [ -s FILE ] True if FILE exists and has a size greater than zero. Thus, you get "empty.txt" if "diff.txt" is not empty. Commented Apr 1, 2012 at 13:48
  • 3
    PS: If you want to check an actual diff call, just check the return value: if diff foo.txt bar.txt; then echo 'No difference' Commented Apr 2, 2012 at 13:13
  • 38
    Test can be negated: if [ ! -s diff.txt ]; then echo "IS EMPTY";else echo "HAS SOMETHING";fi Commented Jun 13, 2014 at 20:44
  • 1
    Beware of the trailing new-line characters. Check the file out with $ cat diff.txt | hexdump -C Commented Feb 20, 2018 at 15:18
  • @DavidRamirez: Note, that [ … ] is different from bash’s native [[ … ]], in that the latter allows some things that would break the former. E.g. w.r.t. quoting or comparison operators. Commented Jan 1, 2023 at 17:42

13 Answers 13

444

try this:

#!/bin/bash -e

if [ -s diff.txt ]; then
        # The file is not-empty.
        rm -f empty.txt
        touch full.txt
else
        # The file is empty.
        rm -f full.txt
        touch empty.txt
fi

Notice incidentally, that I have swapped the roles of empty.txt and full.txt, as @Matthias suggests.

Sign up to request clarification or add additional context in comments.

11 Comments

The shell can help with misspellings. empty=empty.txt; full=full.txt; diff=diff.txt; if [ -s ${diff?} ]; then r=${empty?} t=${full?}; else r=${full?} t=${empty?}; fi; rm ${r?}; touch ${t?}
Using the tool shellcheck can find spelling errors just fine.
Surely this will fail if the file does not exist either? This is supposed to be a check if the file is empty only.
You can also set -u
What is the -e argument passed here in shebang?
|
142
[ -s file.name ] || echo "file is empty"

4 Comments

[[ -s file.name ]] && echo "full" || echo "empty"
[[ -s file.name ]] || { [[ -f file.name ]] && echo 'empty' || echo 'does not exist'; }
@smarber for simple check like this, please use [ ... ] instead of [[ ... ]]. The latter is bashism, which should be used only for incompatible bash checks (e.g. regexp). If you ever happen to write anything which should be POSIX shell portable (e.g. Debian system scripts), you'll appreciate this habit yourself :).
Can you add that The echo command will also run when the file.name does not exist at all
89

[ -s file ] # Checks if file has size greater than 0

[ -s diff.txt ] && echo "file has something" || echo "file is empty"

If needed, this checks all the *.txt files in the current directory; and reports all the empty file:

for file in *.txt; do if [ ! -s $file ]; then echo $file; fi; done

2 Comments

You don't need to do $(ls *.txt, and in fact shouldn't. Some people have defaults set for ls that use the long format (like me) and the shell will already expand *.txt on its own. Just do for file in *.txt instead.
Nice! If you'd like to check all txt files recursively, you can use find like this: for file in $(find . -name '*.txt'); do if [[ ! -s $file ]]; then echo $file; fi; done
29

To check if file is empty or has only white spaces, you can use grep:

if [[ -z $(grep '[^[:space:]]' $filename) ]] ; then
  echo "Empty file" 
  ...
fi

2 Comments

This is the only good answer and should be the accepted one. Using -s does not answer the question. It looks for a file that does exist and has a size of more than 0 bytes.
Wouldn't it be better to do if ! grep -q '[^[:space:]]' "$filename" ; then echo "Empty file"; fi? I think the version above will have to try to parse the entirety of large files, and all non-blank lines will be have to be held in a string and processed with [[ -z ... ].
22

Easiest way for checking if file is empty or not:

if [ -s /path-to-file/filename.txt ]
then
     echo "File is not empty"
else
     echo "File is empty"
fi

You can also write it on single line:

[ -s /path-to-file/filename.txt ] && echo "File is not empty" || echo "File is empty"

Comments

21

While the other answers are correct, using the "-s" option will also show the file is empty even if the file does not exist.
By adding this additional check "-f" to see if the file exists first, we ensure the result is correct.

if [ -f diff.txt ]
then
  if [ -s diff.txt ]
  then
    rm -f empty.txt
    touch full.txt
  else
    rm -f full.txt
    touch empty.txt
  fi
else
  echo "File diff.txt does not exist"
fi

Comments

11

@geedoubleya answer is my favorite.

However, I do prefer this

if [[ -f diff.txt && -s diff.txt ]]
then
  rm -f empty.txt
  touch full.txt
elif [[ -f diff.txt && ! -s diff.txt ]]
then
  rm -f full.txt
  touch empty.txt
else
  echo "File diff.txt does not exist"
fi

Comments

11
[[ -f filename && ! -s filename ]] && echo "filename exists and is empty"

Comments

4

Many of the answers are correct but I feel like they could be more complete / simplistic etc. for example :

Example 1 : Basic if statement

# BASH4+ example on Linux :

typeset read_file="/tmp/some-file.txt"
if [ ! -s "${read_file}" ]  || [ ! -f "${read_file}" ] ;then
    echo "Error: file (${read_file}) not found.. "
    exit 7
fi

if $read_file is empty or not there stop the show with exit. More than once I have had misread the top answer here to mean the opposite.

Example 2 : As a function

# -- Check if file is missing /or empty --
# Globals: None
# Arguments: file name
# Returns: Bool
# --
is_file_empty_or_missing() {
    [[ ! -f "${1}" || ! -s "${1}" ]] && return 0 || return 1
}

Comments

3

Similar to @noam-manos's grep-based answer, I solved this using cat. For me, -s wasn't working because my "empty" file had >0 bytes.

if [[ ! -z $(cat diff.txt) ]] ; then
    echo "diff.txt is not empty"
else
    echo "diff.txt is empty"
fi

2 Comments

The test value is unquoted. Won’t this get into big problems, if diff.txt contains e.g. ` 'x' ]] && rm -rf /home; # `?
this doesn't work either unless diff.txt has non-spaces, although it works if you add quotes, as suggested by @anon
0

I came here looking for how to delete empty __init__.py files as they are implicit in Python 3.3+ and ended up using:

find -depth '(' -type f  -name __init__.py ')' -print0 |
  while IFS= read -d '' -r file; do if [[ ! -s $file ]]; then rm $file; fi; done

Also (at least in zsh) using $path as the variable also breaks your $PATH env and so it'll break your open shell. Anyway, thought I'd share!

Comments

0
  1. (For the guys above) I'm not sure if you really want to use logical operators inside the [[ program. Probably you should use [[ expr_1 ]] && [[ expr_2 ]] instead of [[ expr_1 && expr_2 ]].
  2. The expression [[ -s file.txt ]] also checks if the file exists, so I don't see any reason to use -f before that.

This a simple statement to check if a file exists, is not empty and contains 0:

if [[ ! -s ./example.txt  ]] || grep -q 0 "./example.txt"; then
  echo "example.txt doesn't exist, is empty or contains 0"
else
  echo "example.txt contains 1"

Last note: Mind that empty file isn't always empty:

  • touch example.txt - this file is empty
  • echo "" > example.txt - this file is NOT empty

Comments

-1

My answer is somewhat specific for using with "virtual" file-systems like sysfs. Such kind of file-systems can give wrong results if you'll use the methods mentioned in most of answers here. Because a file can be stat'ed as having non-zero length, but if you try to read its contents you'll get nothing (or I/O error).

cat -n 1 '/path/to/file' &> /dev/null && echo true || echo false

A bit of explanation. Here we try to read the first line from the file and silently ignore its contents (send it to /dev/null). Depending on the exit status, we print "true" or "false".

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.