该计划是将 Java 的所有源代码行递归地收集到一个文件中:
$ find . -name '*.java' | xargs cat >> all.java
但是有一个错误:
cat: ./all.java: input file is output file
该文件all.java
在执行此命令之前不存在,所以我认为可能xargs
正在尝试运行cat >> all.java file1 file2 file3 ...
答案1
首先,您可以放心地忽略该错误。该命令将成功运行,并且它将正确地忽略all.java
自身。它只是让您知道它这样做了。
无论如何,为了避免错误,您可以使用tee
并find's
执行选项:
$ find . -name '*.java' -exec cat {} + | tee all.java
从man find
:
-exec command ;
Execute command; true if 0 status is returned. All following
arguments to find are taken to be arguments to the command until
an argument consisting of `;' is encountered. The string `{}'
is replaced by the current file name being processed everywhere
it occurs in the arguments to the command, not just in arguments
where it is alone, as in some versions of find.
-exec command {} +
This variant of the -exec action runs the specified command on
the selected files, but the command line is built by appending
each selected file name at the end; the total number of invoca‐
tions of the command will be much less than the number of
matched files.
因此,您可以使用-exec
来告诉find
对每个结果运行命令。 被{}
替换为找到的实际文件/目录名称。只是告诉命令在这里结束的+
标记。我使用它而不是因为它将运行更少的命令,因为它将尝试将它们组合成尽可能少的运行。find
\;
或者使用 find!
来排除all.java
:
$ find . -name '*.java' ! -name all.java -exec cat {} + >> all.java
或者通配符:
$ shopt -s globstar
$ cat **/*.java > all.java
答案2
问题是第一的该文件all.java
已创建,然后find
找到它并将其输入到cat
,但它不喜欢它,因为它在那里输出。
可能的解决方案:
$ find . -name '*.java' | xargs cat >> all.j
或者:
$ find . -name '*.java' | xargs cat >> ../all.java