How to check if a file is empty in Bash?
Asked Answered
P

12

343

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 emtpy.txt
fi
Punjab answered 1/4, 2012 at 13:41 Comment(5)
[ -s FILE ] True if FILE exists and has a size greater than zero. Thus, you get "empty.txt" if "diff.txt" is not empty.Larios
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'Maggoty
Test can be negated: if [ ! -s diff.txt ]; then echo "IS EMPTY";else echo "HAS SOMETHING";fiKenyettakenyon
Beware of the trailing new-line characters. Check the file out with $ cat diff.txt | hexdump -CVenereal
@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.Sonnysonobuoy
S
409

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.

Selfregard answered 1/4, 2012 at 13:52 Comment(11)
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?}Boult
Using the tool shellcheck can find spelling errors just fine.Lilias
Surely this will fail if the file does not exist either? This is supposed to be a check if the file is empty only.Waikiki
@geedoubleya: Sure. That's a reasonable point. If the file's existence were relevant (as, of course, it might be), then one might adjust the script accordingly. If you gave the adjusted script as an answer and pinged me, I'd upvote.Selfregard
I think a better example can be used here, more precisely change full.txt and empty.txt to something that makes more sense to what is being checked ... I am tempted to downvote,Cranston
You can also set -uLytta
@WilliamPursell, is '?' for in ${word?} ?Dehumidifier
@Dehumidifier I do not understand your question. When the shell evaluates ${word?}, it throws an error if word is undefined.Boult
@WilliamPursell thx ('what' was missing from my question)Dehumidifier
What is the -e argument passed here in shebang?Janus
@Janus Checked in the man bash: "Subshells spawned to execute command substitutions inherit the value of the -e option from the parent shell."Carotenoid
R
129
[ -s file.name ] || echo "file is empty"
Rickyrico answered 30/12, 2014 at 18:3 Comment(3)
[[ -s file.name ]] && echo "full" || echo "empty"Sabrasabre
[[ -s file.name ]] || { [[ -f file.name ]] && echo 'empty' || echo 'does not exist'; }Isopiestic
@Isopiestic 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 :).Absinthism
H
82

[ -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
Hooded answered 9/5, 2017 at 3:25 Comment(2)
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.Heathenish
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; doneAdrenal
M
27

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
Motorcar answered 8/8, 2019 at 15:52 Comment(1)
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.Hambley
W
19

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
Waikiki answered 5/10, 2017 at 11:48 Comment(0)
H
17

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"
Honeyhoneybee answered 27/3, 2020 at 6:16 Comment(0)
I
10

@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
Isopiestic answered 11/4, 2018 at 10:52 Comment(0)
S
7
[[ -f filename && ! -s filename ]] && echo "filename exists and is empty"
Saiff answered 14/5, 2019 at 13:25 Comment(0)
C
3

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
}
Cranston answered 29/4, 2018 at 18:27 Comment(0)
T
1

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
Tuft answered 18/4, 2022 at 16:41 Comment(2)
The test value is unquoted. Won’t this get into big problems, if diff.txt contains e.g. ` 'x' ]] && rm -rf /home; # `?Sonnysonobuoy
this doesn't work either unless diff.txt has non-spaces, although it works if you add quotes, as suggested by @SonnysonobuoyGuanabara
S
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!

Sergent answered 23/1, 2019 at 16:17 Comment(0)
A
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
Arrearage answered 24/7, 2023 at 8:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.