我想在* nix目录和任何子目录中的每个.java文件的前面添加一个许可证文件。我有这个解决方案,似乎工作正常:
$ cat muppet-license.txt
// LICENSE: // Manuh-manuh
$ for file in `find . -iname "*.java"`; do
cat muppet-license.txt "$file" > "$file.out";
mv "$file.out" "$file";
done
我的问题是,为什么以下查找调用不起作用:
find . -iname "*.java" -exec sh -c 'cat muppet-license.txt "$1" > "$1"' -- {} \;
这导致find找到的第一个文件将“muppet license”重复添加到它的前面 - 该文件似乎在不停止的情况下不断增长。
有人可以解释一下造成这种差异的原因是什么?是否与修改名为$ 1的文件有关,导致find重新找到它作为递归搜索的一部分?有没有人对找到用途的算法的细节有任何好的参考?
答案 0 :(得分:3)
你告诉cat要从你写的同一个文件中读取:
cat muppet-license.txt "$1" > "$1"
因此,cat会读取muppet-license.txt
并将其写入$1
,然后阅读$1
(现在包含许可证)并将许可证再次附加到同一文件的末尾,然后继续阅读已写入的内容,等等,在$1
内一遍又一遍地复制许可文件......
这样的事情应该有效:
find . -iname "*.java" -exec sh -c 'cat muppet-license.txt "$1" > "$1.out"; mv "$1.out" "$1"' -- {} \;
通过将许可证和$1
写入单独的文件$1.out
并在写入后将其移回$1
,可以避免无限循环。差异与find无关,只与sh和cat的调用有关。
答案 1 :(得分:3)
问题在于
cat foo $file > $file
将完全按照你的要求去做,这并不总是显而易见的。 shell执行该命令的第一件事是打开$file
进行写入,从而将其截断为零长度。然后运行cat
,将foo
和$file
的内容连接到$file
,这些内容现在是foo的副本。
答案 2 :(得分:1)
问题不在于查找。如果您执行以下操作,则会发生相同的行为:
cat muppet-license.txt a.java > a.java
是因为cat正在重新读取它正在编写的数据。 shell打开a.java进行写入,将其截断为零长度。然后cat将muppet-license.txt的内容写入a.java,然后打开a.java(现在是muppet-license.txt的副本),并将第一行写入文件的末尾(第2行)线)。然后它读取第二行并将其追加到末尾(写入第3行),并连续重复。