4

Possible Duplicate:
Checking if a directory contains files

I want to see if a directory is empty, so I am using [ as follows:

[ -f "./ini/*"]

And the return value is always 1, even though the directory is not empty. Any ideas what's wrong?

Community
  • 1
  • 1
Yotam
  • 9,789
  • 13
  • 47
  • 68
  • 2
    http://stackoverflow.com/questions/91368/checking-if-a-directory-contains-files – Ivaylo Strandjev Sep 11 '12 at 06:03
  • 1
    Can't work because there's no globbing performed in double quoted strings. You test for the existence of a file named `*` in the ini directory. – Jens Sep 11 '12 at 12:29

5 Answers5

5

Try this:

$ echo "*"   #With quotes

vs.

$ echo *    #No quotes

See the difference? When you put quotes around a string, the shell can't glob to replace the asterisk with the matching files.

There are multitude of ways to get what you want. Simplest is to use the ls command without the test command. The if statement takes the output results of the command you give it. The [...] simply are an alias to the test command. These two statements are equivalent:

$ if test -f foo.txt

$ if [ -f foo.txt ]

Basically, all the test command does is return a 0 if the test is true or a non-zero if the test is false. All the if command does is execute the if statement if the command it's given returns a 0 exit code. The reason I'm going all through this is to say let's forget the test and simply use the ls command.

Assume that you have a file foo.txt, but no file bar.txt. Try the following:

$ ls foo.txt > /dev/null 2>&1
$ echo $?
0
$ ls bar.txt > /dev/null 2>&1
$ echo $?
2

The > /dev/null 2>&1 is used to inhibit all output. Notice that the exit code of the ls command when a file exists is 0 while the exit code of the ls command when the file doesn't exist isn't 0. (It's 2 in this case). Now, let's use that instead of the test command:

if ls ./ini/* > /dev/null 2>&1
then
    echo "There are files in that directory!"
else
    echo "There are no files in that directory"
fi

Notice I don't even bother with the test command (which can be the word test or the [..]).

Hope this makes sense to you. It's sometimes difficult for people to realize that in BASH shell, the if command and the [...] are two separate commands, and all if is doing is running the command it's given and then acting depending upon the exit code of the command it runs.

David W.
  • 105,218
  • 39
  • 216
  • 337
3

Beware of filenames starting with '.', normal globbing or using ls (shudder) will not detect those There are several ways to do this, the simplest I can come up with is:

/home/user1> mkdir ini
/home/user1> cd ini
/home/user1/ini> touch .fred jim tom dick harry
/home/user1/ini> cd ..
/home/user1> declare -a names
/home/user1> names=(./ini/* ./ini/.*)
/home/user1> number_of_files=$(( ${#names[@]} -2 ))
/home/user1> echo $number_of_files
5

The -2 is required to remove . and .. from the list.

c00kiemon5ter
  • 16,994
  • 7
  • 46
  • 48
cdarke
  • 42,728
  • 8
  • 80
  • 84
0
if find ./ini/ -maxdepth 0 -empty | read;
then
echo "Not Empty"
else
echo "Empty"
fi
aurelihein
  • 169
  • 4
  • what is `| read` doing there ? this is not the way to hide output.. – c00kiemon5ter Sep 11 '12 at 13:02
  • The read is both to discard the output and make the expression evaluate to true only when something is read (i.e. /some/dir/ is found empty by find). – aurelihein Sep 11 '12 at 13:05
  • if `find` doesn't find any files it will return `1`. if you want to hide the output use `&>/dev/null` for Bash, and `1>/dev/null 2>&1` for sh. – c00kiemon5ter Sep 11 '12 at 13:09
  • 2
    Got rid of the `test` which is good. However, a simple `ls ./ini/* > /dev/null 2>&1` would be faster and easier. – David W. Sep 11 '12 at 13:20
0

If the output of the command below is 0 then no files in directory (Directory empty) else it has files!

$find "/path/to/check" -type f -exec echo {} \;|wc -l

so for you -

exist=`find "./ini" -type f -exec echo {} \;|wc -l`
if [ $exist -gt 0 ]
then
   echo "Directory has files"
else
   echo "Directory is empty"
fi

Or

if [ `find "./ini" -type f -exec echo {} \;|wc -l` -gt 0 ]
then
   echo "Directory has files"
else
   echo "Directory is empty"
fi
Anjan Biswas
  • 7,746
  • 5
  • 47
  • 77
-2

This works for me

[ "$(ls -A /path/to/directory)" ]

in your case it would be

[ "$(ls -A ./ini/)" ]

you can test it using

[ "$(ls -A /tmp)" ] && echo "Not Empty" || echo "Empty"
Andrea Gherardi
  • 826
  • 1
  • 9
  • 18