87

How can I find all zero-byte files in a directory and its subdirectories?

I have done this:

#!/bin/bash
lns=`vdir -R *.* $dir| awk '{print $8"\t"$5}'`
temp=""
for file in $lns; do
    if test $file = "0"; then
        printf $temp"\t"$file"\n"
    fi
    temp=$file
done

But, I only get results in the current directory, not subdirs, and if any file name contains a space then I get only first word followed by tab

Software Engineer
  • 13,509
  • 5
  • 57
  • 83
Civa
  • 1,688
  • 1
  • 14
  • 29
  • 1
    You might like to read `man find`. – alk Mar 29 '13 at 12:58
  • 1
    Question also posted on [unix&linux](http://superuser.com/q/575235/4714) - please don't post the same question in multiple places. – glenn jackman Mar 29 '13 at 14:34
  • next time im not repeate like this due to problem in my browser in with stackoverflow i posted in superuser but now the problem fixed by clearing history cookies and catche in ie so i asked again here – Civa Mar 29 '13 at 15:57

4 Answers4

185

To print the names of all files in and below $dir of size 0:

find "$dir" -size 0

Note that not all implementations of find will produce output by default, so you may need to do:

find "$dir" -size 0 -print

Two comments on the final loop in the question:

Rather than iterating over every other word in a string and seeing if the alternate values are zero, you can partially eliminate the issue you're having with whitespace by iterating over lines. eg:

printf '1 f1\n0 f 2\n10 f3\n' | while read size path; do
    test "$size" -eq 0 && echo "$path"; done

Note that this will fail in your case if any of the paths output by ls contain newlines, and this reinforces 2 points: don't parse ls, and have a sane naming policy that doesn't allow whitespace in paths.

Secondly, to output the data from the loop, there is no need to store the output in a variable just to echo it. If you simply let the loop write its output to stdout, you accomplish the same thing but avoid storing it.

William Pursell
  • 174,418
  • 44
  • 247
  • 279
36

As addition to the answers above:

If you would like to delete those files

find $dir -size 0 -type f -delete
LinuxLuigi
  • 574
  • 5
  • 13
9

No, you don't have to bother grep.

find $dir -size 0 ! -name "*.xml"
Batcher
  • 177
  • 1
4

Bash 4+ tested - This is the correct way to search for size 0:

find /path/to/dir -size 0 -type f -name "*.xml"

Search for multiple file extensions of size 0:

find /path/to/dir -size 0 -type f \( -iname \*.css -o -iname \*.js \)

Note: If you removed the \( ... \) the results would be all of the files that meet this requirement hence ignoring the size 0.

Mike Q
  • 5,006
  • 2
  • 41
  • 53
  • `-iname` is not portable to some non-GNU implementations of `find` See [here for a list of standard](http://pubs.opengroup.org/onlinepubs/009695399/utilities/find.html) options – Gert van den Berg May 15 '18 at 14:45