Combinez la liste des fichiers texte (trop longue), en ajoutant un séparateur de nouvelle ligne entre

J’ai un répertoire contenant des fichiers texte ~ 300K que je voudrais concaténer en un seul fichier, en séparant le contenu de chaque fichier en utilisant une nouvelle ligne \n . Par exemple

 file1 = 'i like apples' file2 = 'john likes oranges' output = 'i like apples\njohn likes oranges' 

Le problème est que, en raison du grand nombre de fichiers, les commandes comme

 awk '{print}' dir/* combined.txt 

lancer une erreur sur la liste des arguments étant trop longue. Un moyen rapide de contourner ce problème? J’ai essayé de trouver un moyen d’utiliser la tuyauterie mais j’ai échoué jusqu’à présent.

Les fichiers texte ne se terminent pas par un \n .

Pour éviter la longue ligne de commande, vous pouvez utiliser une construction de shell telle qu’une boucle for:

 for f in dir/*; do cat "$f"; printf '\n'; done > combined.txt 

Si l’ordre des fichiers dans le fichier combiné n’a pas d’importance, vous pouvez utiliser find place:

 find dir -type f -exec sed -s '$s/$/\n/' {} + > combined.txt 

Cela utilise find -exec pour minimiser le nombre de fois que la commande dans -exec est appelée, tout en évitant les lignes de commande trop longues.

sed -s '$s/$/\n' remplace la fin de la dernière ligne d’un fichier par une nouvelle ligne; -s s’assure que la modification est appliquée à chaque fichier lorsque plusieurs sont fournis comme arguments.

Un bon moyen de contourner une grande liste de fichiers consiste à utiliser find , ce qui est assez courant sur la plupart des dissortingbutions. Quelque chose du genre:

 find ./dir -type f -exec bash -c "cat \{\} >> combined.txt && echo '' >> combined.txt"\; 

Je ne l’ai pas testé mais cela devrait fonctionner, et a l’avantage de ne jamais construire une liste d’arguments contenant tous les fichiers dans le répertoire

 find . -type f -exec awk 'FNR==1{printf "\n"}1' {} + | tail -n +2 > combined.txt 

FNR==1 est vrai chaque fois que awk lit la première ligne d’un des fichiers. Cela s’applique malheureusement aussi au premier fichier, de sorte que la ligne supplémentaire est supprimée avec tail .

Solution avec GNU Parallel:

 printf '%s\0' * | parallel -0 'cat {}; echo' > combined.txt 

Erreur mineure: Le fichier combattre.txt se terminera par \ n, qui n’est pas spécifié.

Ma conjecture est, cependant, que vous serez contraint par les E / S, donc la solution de Benjamin W. peut être plus rapide.