Jon*_*nik 10 ls bash wildcards files
愚蠢的是,我一直在使用这样的条件作为脚本的一部分:
if [ $(ls FOO* 2> /dev/null) ] # if files named "FOO*" were downloaded
then
echo "Files found"
# ... process and email results
else
echo "Not found"
# ... email warning that no files were found (against expectations)
fi
Run Code Online (Sandbox Code Playgroud)
这适用于零个和一个名为 的文件FOO*
,但如果有多个则失败。从日志中,我发现了几个不同的错误消息:
[: FOO_20131107_082920: unary operator expected
[: FOO_20131108_070203: binary operator expected
[: too many arguments
Run Code Online (Sandbox Code Playgroud)
我的问题是:在 Bashif
条件下,检查名称以 开头的一个或多个文件是否FOO
存在的正确方法是什么?
GNU bash,版本 4.2.25(1)-release (x86_64-pc-linux-gnu)
Chr*_*own 21
发生这种情况是因为您对 ls 的命令替换会输出空格,并且它最终会在传递给[
. 一种不太容易破坏的方法是将文件放在一个数组中,然后检查该数组是否至少有一个成员。
shopt -s nullglob
files=( FOO* )
if (( ${#files[@]} )); then
# there were files
fi
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为((
默认情况下,如果该值不等于 0,则返回 true,并${#files[@]}
获取数组中的项目数(如果有与 glob 匹配的文件,则为 >0)。
你也可以做这样的事情,只要nullglob
没有设置:
if ls FOO* >/dev/null 2>&1; then
# there were files
fi
Run Code Online (Sandbox Code Playgroud)
这只是检查 的退出代码ls
,如果您传递的文件名不存在FOO*
,则该代码将为 1(文字,如果没有匹配的内容(当然,除非您是邪恶的并且有一个名为 的文件FOO*
,在这种情况下它)将返回 0 :-) ))。
请注意,这两者也匹配目录。如果您真的只想匹配常规文件,则需要测试:
for file in FOO*; do
if [[ -f $file ]]; then
# file found, do some stuff and break
break
fi
done
Run Code Online (Sandbox Code Playgroud)
小智 5
上面的多行答案不适合我对单行解决方案而不是修改环境的渴望。这是一个可能适合您的通用单线:
echo $(ls FOO* 2>/dev/null | wc -w)
Run Code Online (Sandbox Code Playgroud)
/dev/null 是因为ls
如果没有文件会引发错误。这只是忽略 ls 并根据“单词”(真正的文件名)的数量计算找到的文件数量。您可以在简单的 if 语句中使用它:
if [ 0 -lt $(ls FOO* 2>/dev/null | wc -w) ]; then
echo "Some FOO is there."
fi
Run Code Online (Sandbox Code Playgroud)
这种方法具有灵活性,不仅可以检查是否存在任何匹配文件,还可以选择检查存在多少匹配文件(只需更改0
和/或-lt
),然后在此基础上进一步进行。
我没有检查包含通配符或空格的文件/文件夹;我怀疑上述方法尤其会给出错误的空格计数,如果需要超过 0 的准确计数,这只是一个问题。我为此尝试的一个解决方法是使用$(ls -l FOO* 2>/dev/null | wc -l)
,它将按行分解列表,因此应该是更能接受留白。