从 find 命令执行 bash 函数

Execute bash function from find command

我在bash中定义了一个函数,它检查两个文件是否存在,比较它们是否相等并删除其中一个。

function remodup {
    F=
    G=${F/.mod/}
    if [ -f "$F" ] && [ -f "$G" ]
    then
        cmp --silent "$F" "$G" && rm "$F" || echo "$G was modified"
    fi
}

然后我想通过查找命令调用此函数:

find $DIR -name "*.mod" -type f -exec remodup {} \;

我也试过 | xargs 语法。 findxargs 都表明 ``remodup` 不存在。

我可以将该函数移动到一个单独的 bash 脚本中并调用该脚本,但我不想将该函数复制到路径目录中(目前),所以我要么需要调用具有绝对路径的函数脚本或始终从同一位置调用调用脚本。

(我可能可以使用 fdupes 来完成这个特定的任务,但我想找到一种方法来实现

  1. find 命令调用函数;
  2. 从另一个脚本的相对路径调用一个脚本;或
  3. 对使用 find 命令找到的文件使用 ${F/.mod/} 语法(或其他 bash 变量操作)。)

您需要先导出函数,使用:

export -f remodup

然后将其用作:

find $DIR -name "*.mod" -type f -exec bash -c 'remodup ""' - {} \;

您可以手动循环遍历 find 的结果。

while IFS= read -rd $'[=10=]' file; do
    remodup "$file"
done < <(find "$dir" -name "*.mod" -type f -print0)

-print0-d $'[=13=]' 使用 NUL 作为分隔符,允许在文件名中换行。 IFS= 确保不会删除文件名开头的空格。 -r 禁用反斜杠转义。所有这些选项的总和是允许在文件名中使用尽可能多的特殊字符,而不会发生混淆。

抛出第三个选项:

find "$dir" -name "*.mod" -type f \
  -exec bash -s -c "$(declare -f remodup)"$'\n'' for arg; do remodup "$arg"; done' _ {} +

这通过 argv 传递函数,而不是通过环境,并且(由于使用 {} + 而不是 {} ;)使用尽可能少的 shell 实例.


我会将 John Kugelman 的答案作为我的第一选择,这是我的第二选择。

鉴于您没有使用 find 的许多功能,您可以使用纯 bash 解决方案来迭代所需的文件。

shopt -s globstar nullglob
for fname in ./"$DIR"/**/*.mod; do
    [[ -f $fname ]] || continue
    f=${fname##*/}
    remodup "$f"
done