Checking from shell script if a directory contains

2019-01-03 21:54发布

From a shell script, how do I check if a directory contains files?

Something similar to this

if [ -e /some/dir/* ]; then echo "huzzah"; fi;

but which works if the directory contains one or several files (the above one only works with exactly 0 or 1 files).

标签: bash unix shell
25条回答
对你真心纯属浪费
2楼-- · 2019-01-03 22:03
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
     echo 'There is something alive in here'
fi
查看更多
Anthone
3楼-- · 2019-01-03 22:03

With some workaround I could find a simple way to find out whether there are files in a directory. This can extend with more with grep commands to check specifically .xml or .txt files etc. Ex : ls /some/dir | grep xml | wc -l | grep -w "0"

#!/bin/bash
if ([ $(ls /some/dir | wc -l  | grep -w "0") ])
    then
        echo 'No files'
    else
        echo 'Found files'
fi
查看更多
唯我独甜
4楼-- · 2019-01-03 22:07

Could you compare the output of this?

 ls -A /some/dir | wc -l
查看更多
唯我独甜
5楼-- · 2019-01-03 22:07
# Checks whether a directory contains any nonhidden files.
#
# usage: if isempty "$HOME"; then echo "Welcome home"; fi
#
isempty() {
    for _ief in $1/*; do
        if [ -e "$_ief" ]; then
            return 1
        fi
    done
    return 0
}

Some implementation notes:

  • The for loop avoids a call to an external ls process. It still reads all the directory entries once. This can only be optimized away by writing a C program that uses readdir() explicitly.
  • The test -e inside the loop catches the case of an empty directory, in which case the variable _ief would be assigned the value "somedir/*". Only if that file exists will the function return "nonempty"
  • This function will work in all POSIX implementations. But be aware that the Solaris /bin/sh doesn't fall into that category. Its test implementation doesn't support the -e flag.
查看更多
我命由我不由天
6楼-- · 2019-01-03 22:07

Small variation of Bruno's answer:

files=$(ls -1 /some/dir| wc -l)
if [ $files -gt 0 ] 
then
    echo "Contains files"
else
    echo "Empty"
fi

It works for me

查看更多
等我变得足够好
7楼-- · 2019-01-03 22:07

ZSH

I know the question was marked for bash; but, just for reference, for zsh users:

Test for non-empty directory

To check if foo is non-empty:

$ for i in foo(NF) ; do ... ; done

where, if foo is non-empty, the code in the for block will be executed.

Test for empty directory

To check if foo is empty:

$ for i in foo(N/^F) ; do ... ; done

where, if foo is empty, the code in the for block will be executed.

Notes

We did not need to quote the directory foo above, but we can do so if we need to:

$ for i in 'some directory!'(NF) ; do ... ; done

We can also test more than one object, even if it is not a directory:

$ mkdir X     # empty directory
$ touch f     # regular file
$ for i in X(N/^F) f(N/^F) ; do echo $i ; done  # echo empty directories
X

Anything that is not a directory will just be ignored.

Extras

Since we are globbing, we can use any glob (or brace expansion):

$ mkdir X X1 X2 Y Y1 Y2 Z
$ touch Xf                    # create regular file
$ touch X1/f                  # directory X1 is not empty
$ touch Y1/.f                 # directory Y1 is not empty
$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ for i in {X,Y}*(N/^F); do printf "$i "; done; echo  # print empty directories
X X2 Y Y2

We can also examine objects that are placed in an array. With the directories as above, for example:

$ ls -F                       # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ arr=(*)                     # place objects into array "arr"
$ for i in ${^arr}(N/^F); do printf "$i "; done; echo
X X2 Y Y2 Z

Thus, we can test objects that may already be set in an array parameter.

Note that the code in the for block is, obviously, executed on every directory in turn. If this is not desirable then you can simply populate an array parameter and then operate on that parameter:

$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories

Explanation

For zsh users there is the (F) glob qualifier (see man zshexpn), which matches "full" (non-empty) directories:

$ mkdir X Y
$ touch Y/.f        # Y is now not empty
$ touch f           # create a regular file
$ ls -dF *          # list everything in the current directory
f X/ Y/
$ ls -dF *(F)       # will list only "full" directories
Y/

The qualifier (F) lists objects that match: is a directory AND is not empty. So, (^F) matches: not a directory OR is empty. Thus, (^F) alone would also list regular files, for example. Thus, as explained on the zshexp man page, we also need the (/) glob qualifier, which lists only directories:

$ mkdir X Y Z
$ touch X/f Y/.f    # directories X and Y now not empty
$ for i in *(/^F) ; do echo $i ; done
Z

Thus, to check if a given directory is empty, you can therefore run:

$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished

and just to be sure that a non-empty directory would not be captured:

$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished

Oops! Since Y is not empty, zsh finds no matches for (/^F) ("directories that are empty") and thus spits out an error message saying that no matches for the glob were found. We therefore need to suppress these possible error messages with the (N) glob qualifier:

$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished

Thus, for non-empty directories we need the qualifier (N/^F), which you can read as: "don't warn me about failures, directories that are not full".

Similarly, for empty directories we need the qualifier (NF), which we can likewise read as: "don't warn me about failures, full directories".

查看更多
登录 后发表回答