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

问题描述

亲爱的

我尝试在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 >> "{}"' \;

但是,命令没有给我想要的结果。我希望对于通过find找到的每个“ U”,“ temp”都将被覆盖。但是我看到先前找到的“ U”的内容被追加到“ temp”,从而累积了其内容。如果我尝试通过以下方法删除“ temp”:

-exec rm -rf temp \;

然后我会收到一个错误

cat:temp:没有这样的文件或目录

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

有人可以说我可能错了吗?我感谢任何提示

亲切的问候。

解决方法

您希望-execdir而不是-exec在与U相同的目录中创建临时文件。重定向应在bash会话中进行:实际上,所有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

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

echo > bar foo 

也可以完成,

> bar echo foo

这是违反直觉的,但还是如此。

您的命令是

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 >> "{}"' \;