【问题标题】:find: missing argument to `-exec' when used in bash in a Chef recipe发现:在厨师食谱中的 bash 中使用时缺少“-exec”的参数
【发布时间】:2026-02-24 08:30:01
【问题描述】:

我需要使用 bash 在 Linux 目录下的几个文件中替换一个字符串。此命令在命令行中运行良好:

find ./ -iname '*.xml' -exec sed -i -e 's/<value>string<\/value>/<value>string01<\/value>/g' {} \;

当我尝试使用 bash 将其放入 shell 时,我收到此错误:

STDERR: find: `-exec' 缺少参数

更新:我的 bash 代码在 Chef 食谱中。代码如下:

bash "change_string_dir" do
    code <<-EOH
         find ./ -iname '*.xml' -exec sed -i -e 's/<value>string<\/value>/<value>string01<\/value>/g' {} \;
    EOH
end

【问题讨论】:

  • 您能否编辑您的 Q 以包含更多脚本以及调用它的命令?你在第 1 行使用#!/bin/bash 吗? STDERR: 是真的印在屏幕上,还是你的评论让我们知道它在哪个管道上?我怀疑您正在使用另一个捕获 I/O 的程序,而该其他程序可能是问题的一部分。
  • 我已经更新了我的问题....
  • 尝试使用code &lt;&lt;-'EOH'(在EOH 周围加上单引号)禁用对字符串内容的Ruby 解释。我怀疑 Ruby 正在吞下分号之前的反斜杠。

标签: ruby bash shell escaping chef-recipe


【解决方案1】:

code&lt;&lt; 行更改为code &lt;&lt;-'EOH'(在EOH 周围加上单引号)。这将是disable Ruby interpretation of the string contents。 Ruby 正在吞下分号前的反斜杠。示例(在irb**... 中添加):

irb(main):004:0> print <<XX     ** No single-quotes
irb(main):005:0" \;
irb(main):006:0" XX
;                               ** the backslash is gone
=> nil
irb(main):007:0> print <<'XX'   ** with single-quotes
irb(main):008:0' \;
irb(main):009:0' XX
\;                              ** the backslash is still there
=> nil

由于 Ruby 在您的 find 命令行末尾去除反斜杠分号,find 永远不会看到 -exec 参数的结尾。

编辑

对于不支持非插值 here-docs 的 Ruby 版本,请手动转义内容。例如:

find ./ -iname '*.xml' -exec sed -i -e 's/<value>string<\\/value>/<value>string01<\\/value>/g' {} \\;
                                                         ^ extra backslashes  - - -^- - - - - - - -^

irb 示例:

irb(main):001:0> print <<-EOH   ** No quotes
irb(main):002:0" \\;            ** Extra backslash
irb(main):003:0" EOH
\;                              ** The backslash is printed

【讨论】:

  • 它对我不起作用......不幸的是,对于 Chef code &lt;&lt;- 'EOH' 来说是一个 sintax 错误
  • @Cesare 已编辑 - 尝试手动转义。 另外你真的做了&lt;&lt;- 'EOH'(连字符后有一个空格)吗?如果是这样,请尝试不带空格 --- &lt;&lt;-'EOH'
  • 好的,它现在可以工作了......我使用find ./ -iname '*.xml' -exec sed -i -e 's/&lt;value&gt;string&lt;\\/value&gt;/&lt;value&gt;string01&lt;\\/value&gt;/g' \\;,不需要使用code &lt;&lt;- 'EOH',所以我继续使用code &lt;&lt;- EOH,就像我原来的代码一样