我需要检查文件夹是否存在,如果存在则执行一个操作,如果不存在则执行另一个操作。我使用 find 来完成此任务,但我无法找到正确的方法:
find /path/to/destination -maxdepth 1 -type d -name "dir*" -exec bash -c '[[ $1 ]] && echo ok || echo "not ok"' _ {} \;
但 bash 部分中的部分是较新执行的,有什么建议吗?
答案1
仅对符合先前条件(和)-exec
的文件执行此操作,并且每个文件执行一次。-name 'dir*'
-type d
在这里,您可能想要使用zsh
并执行类似的操作:
dirs=(/path/to/destination/dir*(N/))
if (($#dirs)); then
echo Found these dirs:
printf ' - %s\n' $dirs
else
echo >&2 No dir found
fi
或者使用 bash 版本 4.4 或更高版本以及find
兼容的 GNU(在使用-maxdepth
GNU 扩展时您必须已经在使用它):
readarray -td '' dirs < <(
find /path/to/destination -maxdepth 1 -type d -name "dir*" -print0)
if ((${#dirs[@]})); then
echo Found these dirs:
printf ' - %s\n' "${dirs[@]}"
else
echo >&2 No dir found
fi
答案2
如果您想查看是否有任何目录与该名称模式匹配,您可以find
为它们打印一些虚拟输出,并查看输出是否为空。例如:
if [[ "$(find -type d -name "dir*" -printf .)" ]] ; then
echo "some matching directory exists"
else
echo "no matching directory exists"
fi
您还可以find
通过-exec bash -c '...' _ {} \;
在-printf
.如果该命令没有产生任何输出,则应该没问题。
如果您需要捕获启动的命令的输出find
并将其与虚拟输出分开,情况确实会变得更糟:您将需要临时文件或重定向技巧。这应该somecmd
在 匹配的任何目录上运行find
,将执行的输出定向somecmd
到脚本 stdout,然后告诉您是否有任何匹配。
exec 3>&1
any=$(find -type d -name "dir*" -printf . -exec bash -c 'somecmd "$1" >&3' _ {} \; )
if [[ "$any" ]] ; then
echo "matching directories were processed"
else
echo "no matching directory exists"
fi
exec 3>&-
当然,如果命令是由find
总是产生输出,不需要虚拟输出。只要捕获任何find
打印,看看它是否是空的。
答案3
它很丑陋,但在 bash 中:
(shopt -s nullglob; if ! [ -z /path/to/destination/dir*/ ] 2>&-; then echo ok; else echo not ok; fi)
启用后nullglob
,/path/to/destination/dir*/
将扩展为:
- 如果没有找到匹配的目录,则什么也不做,在这种情况下测试
-z
成功,因此否定的测试失败; 或所有匹配目录的列表,在这种情况下:
- 如果只有一个目录,则
-z
测试失败 - 如果有多个目录,则测试命令会失败,因为
-z
只需要一个操作数
所以否定的测试通过了。
- 如果只有一个目录,则
例子:
$ if ! [ -z /a* ] 2>&-; then echo ok; else echo not ok; fi
not ok
$ if ! [ -z /b* ] 2>&-; then echo ok; else echo not ok; fi # multiple: /bin /boot
ok
$ if ! [ -z /h* ] 2>&-; then echo ok; else echo not ok; fi # single: /home
ok
这是无法使用扩展测试的一种情况,因为在[[ ... ]]
.