使用 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
echo
将 foo
视为参数,并将其发送到标准输出,我们已将其重定向到 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 >> "{}"' \;
亲爱的,
我已经尝试在 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
echo
将 foo
视为参数,并将其发送到标准输出,我们已将其重定向到 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 >> "{}"' \;