如何在 find -exec 命令中扩展 $()

How to expand $() inside find -exec command

我有一个要导入的 mongodump,显然我正在使用 find 命令来执行此操作。像这样:

find *.bson -type f -exec echo mongoimport --db=abc --collection=$(echo '{}' | sed  s/.bson//g) {} \;

我正在寻找的不是评估我需要的是

mongoimport --db=abc --collection=a a.bson

但我得到的是

mongoimport --db=abc --collection=a.bson a.bson

我使用 sed'{}' 中删除 .bson 后缀的版本无效。我知道它不是障碍物,但我觉得这是否可能。

有什么建议吗?

双重问题:

  1. Shell 扩展: 在 shell 环境中执行命令之前, shell (sh/bash/ksh/zsh) 将执行一系列扩展以构建正在执行的实际命令。执行的扩展有七种:大括号扩展、波浪符扩展、参数和变量扩展、命令替换、算术扩展、单词拆分和路径名扩展。因此,在执行 find 命令之前,它将执行所有替换,包括位于 exec 语句中的命令替换。因此,该命令等同于:

    $ find *.bson -type f -exec echo mongoimport --db=abc --collection={} {} \;
    

    一种前进的方法是使用 single-quotes 禁止命令替换,但这会导致问题二。

  2. find's exec statement is limited: -exec 可以执行的命令仅限于带有可选参数的外部实用程序。因此无法识别各种 shell 特征。直接使用 shell built-ins、函数、条件、管道、重定向等是不可能的,除非包裹在 sh -c 子 shell 之类的东西中.

因此答案应该是:

$ find *.bson -type f -exec /usr/bin/sh -c 'echo mongoimport --db=abc --collection=$(echo {} | sed  s/.bson//g) {}' \;

针对此问题提出不同的策略。

使用 find 和选项 -printf 来准备您的命令。

结果将是要执行的命令列表(每行命令)。

检查和测试命令后,将 find 命令输出保存到文件中,然后 运行 保存文件(作为 bash 脚本)。

或者直接 运行 进入 bash 命令。

1。 find 结果检查:

find . -type f -name "*.bson" -printf "mongoimport --db=abc --collection=%f %f\n" | sed s/.bson//

注意 sed 仅在第一个 .bson 匹配时替换。 不要使用g选项。

2。 运行 处理并检查了 find 输出。

 bash <<< $(find . -type f -name "*.bson" -printf "mongoimport --db=abc --collection=%f %f\n" | sed s/.bson//)