Question cat "fichier d'entrée est le fichier de sortie" tout en essayant de combiner plusieurs fichiers en un seul


Le plan était de collecter toutes les lignes sources de Java dans un fichier, de manière récursive:

$ find . -name '*.java' | xargs cat >> all.java

Mais il y avait une erreur:

cat: ./all.java: input file is output file

Le fichier all.java n'existait pas avant cette commande, alors j'ai pensé que peut-être xargs essayait de courir cat >> all.java file1 file2 file3 ...


4
2018-01-19 13:00


origine


Sonne comme plus d'un unix.stackexchange.com question - user66001
@ user66001 Ça ne rentre pas ici? Je viens d'essayer et je n'ai pas trouvé de résumé de la portée de ce site, sauf pour les passionnés d'informatique et les utilisateurs avertis ... - Evgeni Sergeev
@ user66001 cette question est à 100% sur le sujet ici. Il serait également le bienvenu à Unix et Linux mais c'est aussi un bon choix pour Super utilisateur. - terdon
@terdon & Evgeni Sergeev - Je pensais juste qu'étant donné qu'il s'agissait d'un sous-site spécifique pour les questions liées à Linux / Unix, cette question serait mieux d'y résider. Comprenez que c'est techniquement sur le sujet dans les deux sites. Evgeni Sergeev - Il y a une portée de site ici qui gagnera également un badge pour lire de haut en bas. - user66001


Réponses:


Tout d'abord, vous pouvez ignorer cette erreur en toute sécurité. La commande s'exécutera avec succès et ignorera correctement all.java lui-même C'est simplement en vous faisant savoir qu'il l'a fait.

Quoi qu'il en soit, pour éviter l'erreur que vous pourriez utiliser tee et find's option exec:

$ find . -name '*.java' -exec cat {} + | tee all.java

De 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. 

Donc, vous pouvez utiliser -exec dire find exécuter une commande sur chacun de ses résultats. le {} est remplacé par le nom du fichier / répertoire réel trouvé. le + est juste le marqueur qui dit find que la commande se termine ici. Je l'utilise au lieu de \; car il exécutera moins de commandes car il tentera de les combiner dans le moins de cycles possible.

Ou utiliser les trouvailles ! exclure all.java:

$ find . -name '*.java' ! -name all.java -exec cat {} +  >> all.java

Ou globuler:

$ shopt -s globstar
$ cat **/*.java > all.java

6
2018-01-19 17:51



Googler pour cat {} + est un peu difficile ... et stackoverflow.com/questions/2188199/... ne l'explique pas ... Je ne pense pas avoir déjà vu ce modèle auparavant. - Evgeni Sergeev
@EvgeniSergeev ce sont des options pour find. Voir la mise à jour - terdon


Le problème était que premier le fichier all.java a été créé, puis find trouvé et nourri à cat, ce qui ne lui plaisait pas car il y était sorti.

Solution possible:

$ find . -name '*.java' | xargs cat >> all.j

Ou:

$ find . -name '*.java' | xargs cat >> ../all.java

3
2018-01-19 13:00