cat “输入文件是输出文件”,同时尝试将多个文件合并为一个

Evg*_*eev 4 bash redirection command-line xargs syntax

计划是将 Java 的所有源代码行递归地收集到一个文件中:

$ find . -name '*.java' | xargs cat >> all.java
Run Code Online (Sandbox Code Playgroud)

但是出现了一个错误:

cat: ./all.java: input file is output file
Run Code Online (Sandbox Code Playgroud)

该文件all.java在此命令之前不存在,所以我认为可能xargs正在尝试运行cat >> all.java file1 file2 file3 ...

ter*_*don 6

首先,您可以放心地忽略该错误。该命令将成功运行,并且会正确地忽略all.java自身。它只是让你知道它这样做了。

无论如何,为了避免错误,您可以使用teefind'sexec 选项:

$ find . -name '*.java' -exec cat {} + | tee all.java
Run Code Online (Sandbox Code Playgroud)

来自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. 
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用-exectellfind对其每个结果运行命令。将{}被替换为找到实际的文件/目录名。该+就是这样告诉标记find该命令在这里结束。我使用它而不是\;因为它会运行更少的命令,因为它会尝试将它们组合成尽可能少的运行。

或使用查找!来排除all.java

$ find . -name '*.java' ! -name all.java -exec cat {} +  >> all.java
Run Code Online (Sandbox Code Playgroud)

通配符

$ shopt -s globstar
$ cat **/*.java > all.java
Run Code Online (Sandbox Code Playgroud)