Bash脚本:测试空目录
我想测试一个目录是否不包含任何文件。如果是,我将跳过一些处理。
我尝试了以下操作。
if [./* == "./*"]; then
echo "No new file"
exit 1
fi
这给出了以下错误:
line 1: [: too many arguments
有什么解决办法吗?
我想测试一个目录是否不包含任何文件。如果是,我将跳过一些处理。
我尝试了以下操作。
if [./* == "./*"]; then
echo "No new file"
exit 1
fi
这给出了以下错误:
line 1: [: too many arguments
有什么解决办法吗?
if [-z "$(ls -A /path/to/dir)"]; then
echo "Empty"
else
echo "Not Empty"
fi
另外,如果能在之前检查一下目录是否存在,那就更好了。
一个黑客的,但只有bash的,无PID的方法:
is_empty() {
test -e "$1/"* 2>/dev/null
case $? in
1) return 0 ;;
*) return 1 ;;
esac
}
这利用了test
内置的退出时,如果在-e
后面给出多个参数,就会以2退出。首先,"$1"/*
glob被bash扩展。这导致每个文件只有一个参数。所以
如果没有文件,test -e "$1"*
中的星号不会展开,所以Shell又落回尝试名为*
的文件,返回1。
……除非真的有一个文件的名字正是*
,那么星号就会扩展为嗯,星号,结果和上面的调用一样,即test -e "dir/*"
,只是这次返回0(感谢@TrueY指出这一点。
如果有一个文件,则运行test -e "dir/file"
,返回0.
但如果文件比1多,则运行test -e "dir/file1" "dir/file2"
,bash将其报告为使用错误,即2.
case
将整个逻辑绕了过去,所以只有第一种情况,退出状态为1,才报告为成功。
可能的问题,我还没有检查过:
有更多的文件比允许的参数数量多–我想这可能与2个以上文件的情况类似。
或者有一个空名的文件–我不确定这在任何正常的操作系统/FS上是否可能。
这将在当前的工作目录(.)中执行工作:
[`ls -1A . | wc -l` -eq 0] && echo "Current dir is empty." || echo "Current dir has files (or hidden files) in it."
或者将同样的命令分成三行,以便于阅读。
[`ls -1A . | wc -l` -eq 0] && \
echo "Current dir is empty." || \
echo "Current dir has files (or hidden files) in it."
如果你需要在不同的目标文件夹下运行,就用ls -1A . | wc -l
代替ls -1A <target-directory> | wc -l
。
编辑 .我将-1a
替换为-1A
。我用 0x6& 替换了 0x6& (见 @Daniel 评论)
使用以下方式。
count="$( find /path -mindepth 1 -maxdepth 1 | wc -l )"
if [$count -eq 0] ; then
echo "No new file"
exit 1
fi
这样,你就可以独立于ls
的输出格式。-mindepth
跳过目录本身,-maxdepth
防止递归防御到子目录,以加快速度。
使用一个数组。
files=( * .* )
if (( ${#files[@]} == 2 )); then
# contents of files array is (. ..)
echo dir is empty
fi
我认为最好的解决办法是:
files=$(shopt -s nullglob; shopt -s dotglob; echo /MYPATH/*)
[["$files"]] || echo "dir empty"
感谢 https://stackoverflow.com/a/91558/520567
这是我对答案的匿名编辑,可能对别人有帮助,也可能没有。稍微修改一下文件的数量。
files=$(shopt -s nullglob dotglob; s=(MYPATH/*); echo ${s[*]})
echo "MYPATH contains $files files"
即使文件名中包含空格也能正常工作。
if find "${DIR}" -prune ! -empty -exit 1; then
echo Empty
else
echo Not Empty
fi
EDIT: 我认为这个解决方案在gnu find中可以正常工作,在快速了一下实现。但是,这可能对netbsd的find不起作用。事实上,那个使用的是 stat(2) 的 st_size 字段。手册中描述为
st_size The size of the file in bytes. The meaning of the size
reported for a directory is file system dependent.
Some file systems (e.g. FFS) return the total size used
for the directory metadata, possibly including free
slots; others (notably ZFS) return the number of
entries in the directory. Some may also return other
things or always report zero.
一个更好的解决方案,也更简单,是:
if find "${DIR}" -mindepth 1 -exit 1; then
echo Empty
else
echo Not Empty
fi
另外,第一个解决方案中的-prune是没用的。
EDIT: gnu find 没有 -exit… 上面的解决方案适用于 NetBSD 的 find。对于GNU的find,这个应该是可行的。
if [-z "`find \"${DIR}\" -mindepth 1 -exec echo notempty \; -quit`"]; then
echo Empty
else
echo Not Empty
fi
这对我来说是可行的,可以检查和处理../IN
目录下的文件,因为脚本在../Script
目录下。
FileTotalCount=0
for file in ../IN/*; do
FileTotalCount=`expr $FileTotalCount + 1`
done
if test "$file" = "../IN/*"
then
echo "EXITING: NO files available for processing in ../IN directory. "
exit
else
echo "Starting Process: Found ""$FileTotalCount"" files in ../IN directory for processing."
# Rest of the Code
这是所有伟大的东西 - 只是把它做成一个脚本,这样我就可以检查当前目录下面的空目录。下面的内容应该放到一个叫'findempty'的文件中,放在路径的某个地方,这样bash就能找到它,然后chmod 755运行。我想可以根据你的具体需求轻松修改。
#!/bin/bash
if ["$#" == "0"]; then
find . -maxdepth 1 -type d -exec findempty "{}" \;
exit
fi
COUNT=`ls -1A "$*" | wc -l`
if ["$COUNT" == "0"]; then
echo "$* : $COUNT"
fi
对于当前目录以外的任何一个目录,你可以通过尝试rmdir
来检查它是否为空,因为rmdir
对于非空目录是保证失败的。如果rmdir
成功了,而你其实是想让空目录存活下来,就再mkdir
一次吧。
如果有其他进程可能会因为它们所知道的目录短暂地不存在而变得混乱,就不要使用这个黑客。
如果rmdir
对你不起作用,而且你可能会测试可能包含大量文件的目录,任何依赖shell globbing的解决方案都可能变得缓慢和/或遇到命令行长度限制。在这种情况下,可能最好使用find
。我能想到的最快的 find
解决方案是
is_empty() {
test -z $(find "$1" -mindepth 1 -printf X -quit)
}
这对 GNU 和 BSD 版本的 find
有效,但对 Solaris 版本的 find
则无效,因为它缺少所有这些 0x6& 操作符。爱你的工作,Oracle。