【问题标题】:Execute bash function from find command从 find 命令执行 bash 函数
【发布时间】:2019-10-10 23:31:20
【问题描述】:

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

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

然后我想从 find 命令中调用这个函数:

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

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

我可以将函数移动到单独的 bash 脚本中并调用脚本,但我不想将该函数复制到路径目录中(还),所以我需要使用绝对路径调用函数脚本或者总是从同一位置调用调用脚本。

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

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

【问题讨论】:

    标签: bash xargs


    【解决方案1】:

    你需要先导出函数:

    export -f remodup
    

    然后将其用作:

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 我会写成-d '';写作-d $'\0' 意味着shell 实际上可以在字符串中表示一个NUL(作为终止符除外),它不能也不能。
      • 也就是说——我更喜欢这个选项,它比为每个找到的文件启动一个bash 实例更有效,就像另一个当前建议的答案一样。
      • 在测试中,我发现 for 循环更容易阅读。例如:,, for result in `find "base" -name "keyword"`; do echo $result; done
      • 该方法不安全。它会在带有空格的文件名上失败。正如答案所解释的那样,我在上面所做的一切都是有原因的。
      • 建议使用 while … ; do … ; done &lt; &lt;( find … ) 模式。 here 就是原因。
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        加入第三个选项:

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

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


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

        【讨论】:

        • 为什么使用嵌套的declare -f 而不是export -f
        • @JohnKugelman,因为由于 shellshock 补丁,导出的函数在所有版本的 bash 之间不兼容。如果您调用的 shell 与您所在的 shell 版本不同,则无法保证它实际上会支持您导出的函数。
        猜你喜欢
        • 1970-01-01
        • 2015-06-17
        • 2012-01-05
        • 2012-04-05
        • 1970-01-01
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多