J'ai 10k + fichiers totalisant plus de 20 Go que je dois concaténer en un seul fichier.
Y a-t-il un moyen plus rapide que
cat input_file* >> out
?
La manière préférée serait une commande bash, Python est également acceptable sinon considérablement plus lent.
Non, le chat est sûrement le meilleur moyen de le faire. Pourquoi utiliser python alors qu'il existe un programme déjà écrit en C à cet effet? Cependant, vous pouvez cependant envisager d'utiliser xargs
au cas où la longueur de la ligne de commande dépasse ARG_MAX
et vous avez besoin de plusieurs cat
. En utilisant les outils GNU, cela équivaut à ce que vous avez déjà:
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z |
xargs -0 cat -- >>out
L'allocation de l'espace pour le fichier de sortie en premier peut améliorer la vitesse globale car le système n'aura pas à mettre à jour l'allocation pour chaque écriture.
Par exemple, si sous Linux:
size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z | xargs -r0 cat 1<> out
Un autre avantage est que s'il n'y a pas assez d'espace libre, la copie ne sera pas tentée.
Si sur btrfs
, vous pourriez copy --reflink=always
le premier fichier (qui n'implique aucune copie de données et serait donc quasi instantané), et ajoutez le reste. S'il y a 10000 fichiers, cela ne fera probablement pas beaucoup de différence, sauf si le premier fichier est très volumineux.
Il y a une API pour généraliser cela pour recopier tous les fichiers (le BTRFS_IOC_CLONE_RANGE
ioctl
), mais je n'ai trouvé aucun utilitaire exposant cette API, vous devez donc le faire en C (ou python
ou dans d'autres langages à condition qu'ils puissent appeler arbitrairement ioctl
s).
Si les fichiers source sont clairsemés ou ont de grandes séquences de caractères NUL, vous pouvez créer un fichier de sortie clairsemé (gain de temps et d'espace disque) avec (sur les systèmes GNU):
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out