Find with exec 未按预期工作

Find with exec 未按预期工作

我需要检查文件夹是否存在,如果存在则执行一个操作,如果不存在则执行另一个操作。我使用 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(在使用-maxdepthGNU 扩展时您必须已经在使用它):

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

这是无法使用扩展测试的一种情况,因为在[[ ... ]].

相关内容