GNU/Linux >> Tutoriels Linux >  >> Linux

Compter les lignes dans les fichiers volumineux

Sur un serveur multicœur, utilisez GNU parallel pour compter les lignes de fichiers en parallèle. Après l'impression du nombre de lignes de chaque fichier, bc additionne tous les nombres de lignes.

find . -name '*.txt' | parallel 'wc -l {}' 2>/dev/null | paste -sd+ - | bc

Pour économiser de l'espace, vous pouvez même conserver tous les fichiers compressés. La ligne suivante décompresse chaque fichier et compte ses lignes en parallèle, puis additionne tous les comptes.

find . -name '*.xz' | parallel 'xzcat {} | wc -l' 2>/dev/null | paste -sd+ - | bc

Selon mon test, je peux vérifier que le Spark-Shell (basé sur Scala) est bien plus rapide que les autres outils (GREP, SED, AWK, PERL, WC). Voici le résultat du test que j'ai exécuté sur un fichier qui avait 23782409 lignes

time grep -c $ my_file.txt;

réel 0m44.96suser 0m41.59ssys 0m3.09s

time wc -l my_file.txt;

réel 0m37.57suser 0m33.48ssys 0m3.97s

time sed -n '$=' my_file.txt;

réel 0m38.22suser 0m28.05ssys 0m10.14s

time perl -ne 'END { $_=$.;if(!/^[0-9]+$/){$_=0;};print "$_" }' my_file.txt;

réel 0m23.38suser 0m20.19ssys 0m3.11s

time awk 'END { print NR }' my_file.txt;

réel 0m19.90suser 0m16.76ssys 0m3.12s

spark-shell
import org.joda.time._
val t_start = DateTime.now()
sc.textFile("file://my_file.txt").count()
val t_end = DateTime.now()
new Period(t_start, t_end).toStandardSeconds()

res1 :org.joda.time.Seconds =PT15S


Votre facteur de vitesse limite est la vitesse d'E / S de votre périphérique de stockage, donc changer entre de simples programmes de comptage de nouvelles lignes / modèles n'aidera pas, car la différence de vitesse d'exécution entre ces programmes est susceptible d'être supprimée par la façon dont le disque / stockage / tout ce que vous avez.

Mais si vous avez le même fichier copié sur plusieurs disques/périphériques, ou si le fichier est distribué sur ces disques, vous pouvez certainement effectuer l'opération en parallèle. Je ne connais pas spécifiquement ce Hadoop, mais en supposant que vous puissiez lire un fichier de 10 Go à partir de 4 emplacements différents, vous pouvez exécuter 4 processus de comptage de lignes différents, chacun dans une partie du fichier, et résumer leurs résultats :

$ dd bs=4k count=655360 if=/path/to/copy/on/disk/1/file | wc -l &
$ dd bs=4k skip=655360 count=655360 if=/path/to/copy/on/disk/2/file | wc -l &
$ dd bs=4k skip=1310720 count=655360 if=/path/to/copy/on/disk/3/file | wc -l &
$ dd bs=4k skip=1966080 if=/path/to/copy/on/disk/4/file | wc -l &

Remarquez le & à chaque ligne de commande, donc tout fonctionnera en parallèle ; dd fonctionne comme cat ici, mais permettez-nous de spécifier le nombre d'octets à lire (count * bs octets) et combien ignorer au début de l'entrée (skip * bs octets). Il fonctionne par blocs, d'où la nécessité de spécifier bs comme taille de bloc. Dans cet exemple, j'ai partitionné le fichier de 10 Go en 4 morceaux égaux de 4 Ko * 655360 =2684354560 octets =2,5 Go, un donné à chaque travail, vous pouvez configurer un script pour le faire pour vous en fonction de la taille du fichier et le nombre de travaux parallèles que vous exécuterez. Vous devez également additionner le résultat des exécutions, ce que je n'ai pas fait par manque de capacité de script shell.

Si votre système de fichiers est assez intelligent pour diviser un gros fichier entre de nombreux périphériques, comme un RAID ou un système de fichiers distribué ou quelque chose, et paralléliser automatiquement les demandes d'E/S qui peuvent être mises en parallèle, vous pouvez faire une telle division, en exécutant de nombreux travaux parallèles, mais en utilisant le même chemin de fichier, et vous pouvez toujours avoir un gain de vitesse.

EDIT :Une autre idée qui m'est venue est que si les lignes à l'intérieur du fichier ont la même taille, vous pouvez obtenir le nombre exact de lignes en divisant la taille du fichier par la taille de la ligne, toutes deux en octets. Vous pouvez le faire presque instantanément en un seul travail. Si vous avez la taille moyenne et que vous ne vous souciez pas exactement du nombre de lignes, mais que vous souhaitez une estimation, vous pouvez effectuer la même opération et obtenir un résultat satisfaisant beaucoup plus rapidement que l'opération exacte.


Essayez :sed -n '$=' filename

Le chat n'est pas non plus nécessaire :wc -l filename est suffisant à votre manière actuelle.


Linux
  1. Comment compter le nombre de lignes dans un fichier après une correspondance Grep ?

  2. Commande wc Linux

  3. Comment compter les lignes dans un document ?

  4. Utilisation de nc pour transférer un fichier volumineux

  5. Comment compter le nombre total de lignes de fichiers trouvés ?

Copier des fichiers sous Linux

Trouver des fichiers volumineux sous Linux

Comment diviser de gros fichiers audio sous Linux

5 façons de compter le nombre de lignes dans un fichier

Comment télécharger des fichiers volumineux via le gestionnaire de fichiers

Commande Linux wc - Nombre de mots, lignes, caractères dans un fichier