使用 find 和 cat 复制多个文件的内容

Using find and cat to duplicate the content of multiple files

亲爱的,

我已经尝试在 bash 脚本中组合使用“find”和“cat”来复制子目录中数百个文件的内容:

find ./inlet3/* -type f -name 'U' -exec bash -c 'cat "{}"' \; > temp -exec bash -c 'cat temp >> "{}"' \;

查看给定的命令,我打算先将每个“U”的内容复制到一个名为“temp”的临时文件中,该文件应该是每次在bash所在的目录中创建的脚本存在。这部分应该通过以下方法实现:

-exec bash -c 'cat "{}"' \; > temp

“temp”的内容随后应附加到“U”,以获得包含重复内容的文件。这部分应该通过给定的方法完成:

-exec bash -c 'cat temp >> "{}"' \;

但是,该命令没有给我想要的结果。我预计对于通过查找找到的每个“U”,“temp”都会被覆盖。但是我看到以前找到的“U”的内容被附加到“temp”,累积了它的内容。如果我尝试使用以下方法删除“temp”:

-exec rm -rf temp \;

然后我会收到一个错误:

cat: temp: No such file or directory

为了简单起见,我省略了一些其他 -exec 选项。

谁能告诉我哪里错了?我很感激任何提示。

亲切的问候。

您希望 -execdir 而不是 -exec 在与 U 相同的目录中创建临时文件。并且重定向应该在 bash 会话中:实际上所有 shell操作可以运行在同一个shell:

find ... -execdir sh -c 'temp=$(mktemp) && cat "{}" > "$temp" && cat "$temp" >> "{}" && rm "$temp"'

如果安装 moreutils 包,则可以使用 sponge 而无需创建临时文件:

find ... -execdir sh -c '{ cat "{}"; cat "{}"; } | sponge "{}"'

传统上,我们说

echo foo > bar

echofoo 视为参数,并将其发送到标准输出,我们已将其重定向到 bar... 但不必这样写.事实上,echo 甚至不知道它的输出已被重定向。那是处理流的解析器,所以结果意味着您可以用一些奇怪的方式编写命令 -

echo > bar foo 

同样有效,如上

> bar echo foo

这是 counter-intuitive,但仍然是事实。

你的命令是

find ./inlet3/* -type f -name 'U' -exec bash -c 'cat "{}"' \; > temp -exec bash -c 'cat temp >> "{}"' \;

这在功能上与

相同
find ./inlet3/* -type f -name 'U' -exec bash -c 'cat "{}"' \; -exec bash -c 'cat temp >> "{}"' \;  > temp

> temp find ./inlet3/* -type f -name 'U' -exec bash -c 'cat "{}"' \; -exec bash -c 'cat temp >> "{}"' \;

因此,find 的所有输出都进入 temp

你想要的是

find ./inlet3/* -type f -name 'U' -exec bash -c 'cat "{} >| temp"' \; -exec bash -c 'cat temp >> "{}"' \;

除非你 set -o noclobber > 的结果在功能上与 >| 相同,但是当我想要截断时我倾向于明确。永远不会痛。

正如 Glenn Jackman 指出的那样,子壳越少越好,所以 -

find ./inlet3/* -type f -name 'U' -exec bash -c 'cat "{}" >| temp && cat temp >> "{}"' \;