1

我读过很多次,如果我想在所有子目录上执行某些东西,我应该运行类似以下之一的东西:

find . -name '*' -exec command arguments {} \;

find . -type f -print0 | xargs -0 command arguments

find . -type f | xargs -I {} command arguments {} arguments

问题是它与 corefunctions 一起工作得很好,但当命令是用户定义的函数或脚本时,它就不像预期的那样。如何解决?

所以我正在寻找的是一行代码或一个脚本,我可以在其中替换commandormyfunction并且myscript.sh它从当前目录转到每个子目录并在那里执行这样的函数或脚本,无论我提供什么参数。

以另一种方式解释,我希望在所有子目录上都可以像for file in *; do command_myfunction_or_script.sh arguments $file; done在当前目录上一样工作。

4

4 回答 4

2

而不是-exec,尝试-execdir

在某些情况下,您可能需要使用bash

foo () { echo $1; }
export -f foo
find . -type f -name '*.txt' -exec bash -c 'foo arg arg' \;

最后一行可能是:

find . -type f -name '*.txt' -exec bash -c 'foo "$@"' _ arg arg \;

取决于什么 args 可能需要扩展以及何时扩展。下划线代表$0

如果需要,您可以-execdir在我拥有-exec的地方使用。

于 2012-06-11T16:34:36.257 回答
1

可能有一些方法可以将 find 与函数一起使用,但它不会非常优雅。如果你有 bash 4,你可能想做的是使用 globstar:

shopt -s globstar
for file in **/*; do
    myfunction "$file"
done

如果您正在寻找与 POSIX 或更旧版本的 bash 的兼容性,那么当您调用 bash 时,您将被迫获取定义您的函数的文件。所以是这样的:

find <args> -exec bash -c '. funcfile;
    for file; do
        myfunction "$file"
    done' _ {} +

但这只是丑陋的。当我达到这一点时,我通常只是将我的函数放在我的脚本中PATH并使用它。

于 2012-06-11T15:48:31.313 回答
1

您提供的示例,例如:

find . -name '*' -exec command arguments {} \;

不要从当前目录转到每个子目录并在command那里执行,而是从当前目录执行command,并将 find 列出的每个文件的路径作为参数。

如果您想要实际更改目录并执行脚本,您可以尝试以下操作:

STDIR=$PWD; IFS=$'\n'; for dir in $(find . -type d); do cd $dir; /path/to/command; cd $STDIR; done; unset IFS

此处保存当前目录,STDIR并将 bash 内部字段分隔符设置为换行符,因此名称不会在空格上拆分。然后对于返回的每个目录 ( -type d) find,我们cd到该目录,执行命令(在此处使用完整路径,因为更改目录会破坏相对路径),然后 cd 回到起始目录。

于 2012-06-11T16:04:58.053 回答
1

如果您想使用 bash 函数,这是一种方法。

work ()
{
  local file="$1"
  local dir=$(dirname $file)
  pushd "$dir"
    echo "in directory $(pwd) working with file $(basename $file)"
  popd
}
find . -name '*' | while read line;
do
   work "$line"
done
于 2012-06-11T17:45:33.947 回答