在 find 中使用 zsh 函数?

在 find 中使用 zsh 函数?

我在 OS X 上定义了一个名为 的函数,finderpackage该函数尝试根据 Finder 确定文件夹实际上是否是“包”(也有点错误地称为“包”)。

我的预期用途是限制find进入此类文件夹,这有时很有用。

一个应用程序将查找子树中文件的大小,同时处理实际上是文件夹的应用程序、框架、文档格式,并且类似于单个“文件”,就像 Finder 一样:

find . -xdev \( -exec finderpackage {} \; -exec du -sk {} \; -prune \) -or \( -type f -exec du -k {} \; \)

然而,这个例子并不能像find抱怨的那样工作:find: finderpackage: No such file or directory

我可以不以这种方式使用 zsh 函数吗?

(当然我可以将其重写为脚本,我只是好奇我是否错过了有关如何使用函数的一些内容?)

答案1

函数是 shell 语言的特性。/bin/zsh是一个命令,是zsh语言的解释器。find是另一个旨在查找文件的命令。有了-exec,就可以执行一个命令。 zsh 函数不是命令。

find需要zsh解释函数中的代码。为此,它需要zsh以某种方式调用,告诉它加载该函数的代码并使用它找到的文件运行它。可以这样做,例如:

find ... -exec zsh -c "(){$functions[finderpackage];}"' "$@"' zsh {} \; ...

(在上面,我们zsh 使用内联脚本(with -c)进行调用,其内容使用匿名函数((){code} args),其中代码是从finderpackage调用该命令的 shell 中的函数的代码复制而来的find)。

但这意味着zsh每个文件调用一个命令,这将是非常低效的。

zshglobbing 具有递归功能和限定符,这使得它几乎等同于,find但不幸的是,它缺少的一件事是控制如何以任意方式完成目录遍历的能力。

您可以根据名称修剪目录,例如:

setopt extendedglob
print -rl -- (^*.pkg/)#*(.)

修剪目录*.pkg。但是你不能修剪那些目录老的或者例如包含这个或那个文件。为此,您必须手动进行目录遍历。

find你可以做的一件事是作为 a进行交互coproc并使用它,尽管这也不会非常有效-ok

coproc stdbuf -o0 find . -type f -exec printf 'f:%s\0' {} \; -o \
  -type d -exec printf 'd:%s\0' {} \; -ok true \; -prune 2> /dev/null
while IFS=: read -rpd '' type file; do
  case $type in
    (d)
      if finderpackage $file; then
        print -p y
        du -sk $file
      else
        print -p n
      fi;;
    (f)
      du -k $file
  esac
done

相关内容