从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 sh
和zsh
但是对于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 -> dd
pipe与输出截尾随机(如果我使用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