Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash测试一组目录是否存在_Bash - Fatal编程技术网

bash测试一组目录是否存在

bash测试一组目录是否存在,bash,Bash,将文档存储在包含“每日”目录的文件系统中,例如20050610。在bash脚本中,我想列出这些目录中几个月的文件。因此,我正在运行find命令find/200506*-typef>>jun2005.lst。要在执行find命令之前检查此目录集是否不是空集。然而,如果我使用if[-d200506*]我会得到一个“太多的争论错误。我如何才能避免这个问题?” S=200506* if [ ${#S} -gt 6 ]; then echo haz filez! else echo no

将文档存储在包含“每日”目录的文件系统中,例如20050610。在bash脚本中,我想列出这些目录中几个月的文件。因此,我正在运行find命令
find/200506*-typef>>jun2005.lst
。要在执行find命令之前检查此目录集是否不是空集。然而,如果我使用
if[-d200506*]
我会得到一个“太多的争论错误。我如何才能避免这个问题?”

S=200506*

if [ ${#S} -gt 6 ]; then
    echo haz filez!
else
    echo no filez
fi
不是很优雅,但是没有任何外部工具/命令(如果不认为“[”是外部工具/命令)


线索是,如果有一些文件匹配,那么“S”变量将包含以空格分隔的名称。否则,它本身将包含一个“200506*”字符串。

您可以像这样告诉我们
ls

  if [ -n "$(ls -d | grep 200506)" ]; then
        # There are directories with this pattern
  fi

因为在大多数shell中,命令行长度是有限制的:像“$(ls-d | grep 200506)”或/path/200506*之类的任何东西都有超出限制的风险。我不确定替换和全局扩展在BASH中是否算在内,但我假设是这样。您必须对其进行测试,并检查BASH文档和源代码以确定

答案在于简化你的问题

find <path>/200506* -type f -exec somescript '{}' \;
将june2005.lst传递给脚本(建议:使用一个环境变量),并处理200506*可能扩展到过大的文件路径的任何可能性,留给OP作为练习;)

将整个过程集成到一个管道中或采用一种更通用的脚本语言可以通过最小化生成的shell数量来提高性能。现在这将很有趣。这里有一个提示,使用-exec和另一个程序(awk、perl等)作为单行筛选器的一部分执行目录测试,并将>>june2005.lst保留在find命令上。

您的“参数过多”错误不是由于文件数量过多并且超过了命令行参数限制。它是由于有一个或两个以上的目录与glob匹配。您的glob“200506*“扩展为类似“200506012005060220050603…”的内容,
-d
测试只需要一个参数

$ mkdir test
$ cd test
$ mkdir a1
$ [ -d a* ]    # no error
$ mkdir a2
$ [ -d a* ]
-bash: [: a1: binary operator expected
$ mkdir a3
$ [ -d a* ]
-bash: [: too many arguments
zed_0xff的答案是正确的,但我会使用不同的方法:

shopt -s nullglob
path='/path/to/dirs'
glob='200506*/'
outfile='jun2005.lst'
dirs=("$path"/$glob)  # dirs is an array available to be iterated over if needed
if (( ${#dirs[@]} > 0 ))
then
    echo "directories found"
    # append may not be necessary here 
    find "$path"/$glob -type f >> "$outfile"
fi
“$path”/$glob
“$path/$glob”
中引号的位置对于该工作至关重要

编辑:


为排除与glob匹配的文件(因此只包括目录)和处理非常罕见的类似glob的目录(“200506*”)而进行的更正
-d
并没有限制
ls
只列出目录,它只是阻止它列出目录的内容,所以
ls-d
根本不列出任何内容。你可能是说
ls-d*/
注意到-d需要一个参数。因为被测试的目录是“每日”的在一个月内可以达到31个。我有几种不同的“种类”这就意味着,如果中间的一个失败了,我假设下面的一个没有执行,整个脚本都失败了。这是正确的吗?丹尼斯的解决方案将在我的脚本的上下文中工作。FYI,没有文件。s匹配名称中的glob,没有目录与glob完全匹配。@吉姆·琼斯:我不确定我是否明白你的意思。你可以这样做:
globs=('200506*/'200507*/'200508*');outfiles=('jun2005”“jul2005”“aug2005”);subdirs=(abc);对于${globs[@]}中的glob;do outfilebase=${outfiles[I++};对于${subdirs[@}中的subdir do;do path=“/top/of/path/$dir”outfile=“$outfilebase.$subdir.lst”dirs=…[如上]…如果…查找…否则回显“在$subdir下找不到$glob的目录”;fi
[未测试]
shopt -s nullglob
path='/path/to/dirs'
glob='200506*/'
outfile='jun2005.lst'
dirs=("$path"/$glob)  # dirs is an array available to be iterated over if needed
if (( ${#dirs[@]} > 0 ))
then
    echo "directories found"
    # append may not be necessary here 
    find "$path"/$glob -type f >> "$outfile"
fi
prefix="/tmp/path"
glob="200611*"
n_dirs=$(find $prefix -maxdepth 1 -type d -wholename "$prefix/$glob" |wc -l)
if [[ $n_dirs -gt 0 ]];then 
   find $prefix -maxdepth 2 -type f -wholename "$prefix/$glob" 
fi