从shell脚本检查目录是否包含文件

从shell脚本中,如何检查目录是否包含文件?

类似的东西

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

但是如果目录包含一个或多个文件(上面的文件只能与0或1个文件一起使用),那么这种方法是有效的。

到目前为止,解决scheme使用ls 。 这是一个所有的bash解决scheme:

 #!/bin/bash shopt -s nullglob dotglob # To include hidden files files=(/some/dir/*) if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi 

三个最好的窍门


shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))

这个技巧是100% bash并调用(派生)一个子shell。 这个想法来自Bruno De Fraine ,并由teambob的评论改进。

 files=$(shopt -s nullglob dotglob; echo your/dir/*) if (( ${#files} )) then echo "contains files" else echo "empty (or does not exist or is a file)" fi 

注意:空目录和不存在的目录(甚至当提供的path是文件时)没有区别。

对于#bash IRC频道的“官方”常见问题,有一个类似的select和更多的细节(以及更多的例子)

 if (shopt -s nullglob dotglob; f=(*); ((${#f[@]}))) then echo "contains files" else echo "empty (or does not exist, or is a file)" fi 

[ -n "$(ls -A your/dir)" ]

这个诀窍是从nixCraft 2007年发表的文章中得到的启示。Andrew Taylor在2008年回答,2011年在gr8can8dian回答。

 if [ -n "$(ls -A your/dir)" ] then echo "contains files (or is a file)" else echo "empty (or does not exist)" fi 

或者单行双语版本:

 [[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty" 

注意:当目录不存在时, ls返回$?=2 。 但是一个文件和一个空目录没有区别。


[ -n "$(find your/dir -prune -empty)" ]

最后一个技巧是从gravstar的回答中-maxdepth 0灵感的,其中-maxdepth 0-prune取代,并由-maxdepth 0的评论改进。

 if [ -n "$(find your/dir -prune -empty)" ] then echo "empty (directory or file)" else echo "contains files (or does not exist)" fi 

使用-type d的变体:

 if [ -n "$(find your/dir -prune -empty -type d)" ] then echo "empty directory" else echo "contains files (or does not exist or is not a directory)" fi 

说明:

  • find -prune类似于使用较less字符的find -maxdepth 0
  • find -empty打印空目录和文件
  • find -type d只打印目录

注意:你也可以用下面的[ -n "$(find your/dir -prune -empty)" ]版本replace[ -n "$(find your/dir -prune -empty)" ]

 if [ `find your/dir -prune -empty` ] then echo "empty (directory or file)" else echo "contains files (or does not exist)" fi 

最后一个代码适用于大多数情况,但要注意恶意path可以表示一个命令。

以下情况如何:

 if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi 

这样就不需要生成目录内容的完整列表。 read是放弃输出,只有当读取的东西(即/some/dir/find空的find )时,使expression式评估为真。

尝试:

 if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi 
 # Works on hidden files, directories and regular files ### isEmpty() # This function takes one parameter: # $1 is the directory to check # Echoes "huzzah" if the directory has files function isEmpty(){ if [ "$(ls -A $1)" ]; then echo "huzzah" else echo "has no files" fi } 

注意与很多文件的目录! 可能需要一些时间来评估ls命令。

国际海事组织最好的解决scheme是使用的

 find /some/dir/ -maxdepth 0 -empty 
 DIR="/some/dir" if [ "$(ls -A $DIR)" ]; then echo 'There is something alive in here' fi 

你能比较这个输出吗?

  ls -A /some/dir | wc -l 
 #检查目录是否包含任何非隐藏文件。
 #
 #用法:if isempty“$ HOME”; 然后回显“欢迎回家”; 科幻
 #
是空的() {
    为_ief $ 1 / *; 做
        如果[-e“$ _ief”]; 然后
            返回1
        科幻
     DONE
    返回0
 }

一些实施说明:

  • for循环避免了对外部ls进程的调用。 它仍然读取一次所有的目录条目。 这只能通过编写一个明确使用readdir()的C程序来优化。
  • 循环内的test -e捕获空目录的情况,在这种情况下,variables_ief将被赋值为“somedir / *”。 只有该文件存在,该函数才会返回“非空”
  • 这个函数可以在所有POSIX实现中使用。 但请注意,Solaris / bin / sh不属于该类别。 它的test实现不支持-e标志。

这可能是一个非常迟的反应,但这是一个有效的解决scheme。 这行只识别文件的存在! 如果目录存在,它不会给你一个错误的肯定。

 if find /path/to/check/* -maxdepth 0 -type f | read then echo "Files Exist" fi 

这告诉我目录是空的还是不是它包含的文件的数量。

 directory="/some/dir" number_of_files=$(ls -A $directory | wc -l) if [ "$number_of_files" == "0" ]; then echo "directory $directory is empty" else echo "directory $directory contains $number_of_files files" fi 
 dir_is_empty() { [ "${1##*/}" = "*" ] } if dir_is_empty /some/dir/* ; then echo "huzzah" fi 

假设你没有一个名为*/any/dir/you/check ,它应该在bash dash busybox shzsh但是对于zsh,则需要unsetopt nomatch

性能应该可以与使用* (glob)的任何ls相比,我猜对于有很多节点的目录会很慢(我的/usr/bin有超过3000个文件的速度并不慢),至less会占用足够的内存来分配所有的dir /文件名(和更多),因为它们都作为parameter passing(parsing)到函数中,一些shell可能对参数数量和/或参数长度有限制。

一个便携的快速O(1)零资源的方式来检查一个目录是否是空的将是很好的。

更新

上面的版本没有考虑隐藏的文件/目录,以防需要进行更多的testing,例如Rich's sh(POSIX shell)技巧中的is_empty

 is_empty () ( cd "$1" set -- .[!.]* ; test -f "$1" && return 1 set -- ..?* ; test -f "$1" && return 1 set -- * ; test -f "$1" && return 1 return 0 ) 

但是,我正在考虑这样的事情:

 dir_is_empty() { [ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ] } 

有些担心尾随斜线与参数和发现输出时,目录空是空的,并尾随换行符(但这应该很容易处理),悲伤地在我的busybox sh显示什么可能是一个错误find -> ddpipe与输出截尾随机(如果我使用cat的输出总是相同的,似乎是dd与参数count )。

布鲁诺的答案差异很小:

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

这个对我有用

 if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi; 

我很惊讶关于空目录的wooledge指南没有提到。 本指南以及所有关于这个问题的提问都是必读的。

从该页面注意:

切勿尝试parsingls输出。 即使是ls – 一个解决scheme可能会中断(例如在HP-UX上,如果你是root的话,ls -A和你做的根本不一样 – 不,我不能做出令人难以置信的东西笨)。

事实上,人们可能希望完全避免直接的问题。 通常人们想知道一个目录是否是空的,因为他们想要做一些涉及其中的文件的东西,等等。 例如,其中一个基于查找的例子可能是一个合适的解决scheme:

  # Bourne find "$somedir" -type f -exec echo Found unexpected file {} \; find "$somedir" -maxdepth 0 -empty -exec echo {} is empty. \; # GNU/BSD find "$somedir" -type d -empty -exec cp /my/configfile {} \; # GNU/BSD 

最常见的是,真正需要的是这样的:

  # Bourne for f in ./*.mpg; do test -f "$f" || continue mympgviewer "$f" done 

换句话说,问这个问题的人可能认为需要一个明确的空目录testing来避免像mympgviewer这样的错误信息:./*.mpg:实际上不需要这样的testing时,没有这样的文件或目录。

到目前为止,我还没有看到一个使用grep的答案,我认为这会给一个更简单的答案(没有太多奇怪的符号!)。 以下是我将如何检查使用bourne shell的目录中是否存在任何文件:

这将返回目录中的文件数量:

 ls -l <directory> | egrep -c "^-" 

你可以在写入目录的地方填写目录path。 pipe道的前半部分确保每个文件的输出的第一个字符都是“ – ”。 egrep然后使用正则expression式来计算以该符号开始的行数。 现在你所要做的就是存储你获得的数字,并使用反引号进行比较:

  #!/bin/sh fileNum=`ls -l <directory> | egrep -c "^-"` if [ $fileNum == x ] then #do what you want to do fi 

x是你select的variables。

混合修剪的东西和最后的答案,我得到了

 find "$some_dir" -prune -empty -type d | read && echo empty || echo "not empty" 

这也适用于空间的path

bash简单回答:

 if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi; 

我会去find

 if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then echo "$dir has NO files" else echo "$dir has files" 

这将检查目录中仅查找文件的输出,而不通过子目录。 然后使用man test-z选项检查输出:

  -z STRING the length of STRING is zero 

看到一些结果:

 $ mkdir aaa $ dir="aaa" 

空方向:

 $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty" empty 

只是在其中:

 $ mkdir aaa/bbb $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty" empty 

目录中的文件:

 $ touch aaa/myfile $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty" $ rm aaa/myfile 

子目录中的文件:

 $ touch aaa/bbb/another_file $ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty" empty 

尝试使用命令查找。 指定硬编码的目录或参数。 然后启动find来search目录内的所有文件。 检查find的返回值是否为null。 回应find的数据

 #!/bin/bash _DIR="/home/user/test/" #_DIR=$1 _FIND=$(find $_DIR -type f ) if [ -n "$_FIND" ] then echo -e "$_DIR contains files or subdirs with files \n\n " echo "$_FIND" else echo "empty (or does not exist)" fi 

我不喜欢ls - A解决scheme发布。 最有可能的是你想testing目录是否为空,因为你不想删除它。 下面是这样做的。 但是,如果你只是想logging一个空文件,肯定删除并重新创build它,然后列出可能无限的文件?

这应该工作…

 if ! rmdir ${target} then echo "not empty" else echo "empty" mkdir ${target} fi 

testing一个特定的目标目录

 if [ -d $target_dir ]; then ls_contents=$(ls -1 $target_dir | xargs); if [ ! -z "$ls_contents" -a "$ls_contents" != "" ]; then echo "is not empty"; else echo "is empty"; fi; else echo "directory does not exist"; fi; 

适用于我这个(当目录存在):

 some_dir="/some/dir with whitespace & other characters/" if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; fi 

完整检查:

 if [ -d "$some_dir" ]; then if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; else "Dir is NOT empty" fi fi