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.