Come elencare il numero di righe di ogni file in una directory in formato leggibile dall'uomo.


41

Ho un elenco di directory e sottodirectory che contengono file CSV di grandi dimensioni. Ci sono circa 500 milioni di righe in questi file, ognuna è un record. Mi piacerebbe sapere

  1. Quante righe ci sono in ciascun file.
  2. Quante linee ci sono nella directory.
  3. Quante righe in totale

Soprattutto, ho bisogno di questo in un "formato leggibile dall'uomo", ad es. 12.345.678 anziché 12345678

Sarebbe bello imparare a farlo in 3 modi. Strumenti semplici di bash alla vaniglia, awk ecc. E perl (o python).

Risposte:


57

Quante righe ci sono in ciascun file.

Usa wc, in origine per il conteggio delle parole, credo, ma può fare linee, parole, caratteri, byte e la lunghezza della linea più lunga. L' -lopzione dice di contare le righe.

wc -l <filename>

Questo genererà il numero di righe in:

$ wc -l /dir/file.txt
32724 /dir/file.txt

Puoi anche reindirizzare i dati a wc:

$ cat /dir/file.txt | wc -l
32724
$ curl google.com --silent | wc -l
63

Quante linee ci sono nella directory.

Provare:

find . -name '*.pl' | xargs wc -l

un altro one-liner:

( find ./ -name '*.pl' -print0 | xargs -0 cat ) | wc -l

A proposito, il wccomando conta i nuovi codici di linee, non le linee. Quando l'ultima riga del file non termina con un nuovo codice di riga, questo non verrà conteggiato.

Puoi usare grep -c ^, esempio completo:

#this example prints line count for all found files
total=0
find /path -type f -name "*.php" | while read FILE; do
     #you see use grep instead wc ! for properly counting
     count=$(grep -c ^ < "$FILE")
     echo "$FILE has $count lines"
     let total=total+count #in bash, you can convert this for another shell
done
echo TOTAL LINES COUNTED:  $total

Quante righe in totale

Non sono sicuro di aver capito che hai richiesto correttamente. ad es. questo produrrà risultati nel seguente formato, mostrando il numero di righe per ciascun file:

# wc -l `find /path/to/directory/ -type f`
 103 /dir/a.php
 378 /dir/b/c.xml
 132 /dir/d/e.xml
 613 total

In alternativa, per visualizzare solo il numero totale di nuovi caratteri di riga senza il numero di file per file al seguente comando può rivelarsi utile:

# find /path/to/directory/ -type f -exec wc -l {} \; | awk '{total += $1} END{print total}'
 613

Soprattutto, ho bisogno di questo in un "formato leggibile dall'uomo", ad es. 12.345.678 anziché 12345678

Bash ha una funzione printf integrata:

printf "%0.2f\n" $T

Come sempre, ci sono molti metodi diversi che potrebbero essere utilizzati per ottenere gli stessi risultati menzionati qui.


A proposito, come posso usare printf nei tuoi esempi? Ho provato a collegarlo da wc -l, ma non ha funzionato.
Esatonico

prova> trova. -name '* .pl' | xargs wc -l | awk '{printf ("% 0.2f", $ 1)} {print $ 2}' cambia l'output di 'printf' per le tue esigenze
malyy

Questo non aggiunge virgole al numero per renderlo più leggibile dall'uomo però. Aggiunge solo uno zero alla fine.
Esatonico

echo 1000000000000 | xargs printf "% 'd \ n" 1.000.000.000.000
Esatonico

1
@Hexatonic printfnon legge i suoi argomenti stdin, ma piuttosto dalla riga di comando (confronta piping con echovs piping a cat; catlegge da stdin, echonon lo fa). Utilizzare invece printf "$(find ... | xargs ...)"per fornire l'output come argomenti a printf.
BallpointBen,

13

In molti casi, combinare il wccomando e il carattere jolly *può essere sufficiente.
Se tutti i tuoi file si trovano in una singola directory puoi chiamare:

wc -l src/*

Puoi anche elencare diversi file e directory:

wc -l file.txt readme src/* include/*

Questo comando mostrerà un elenco dei file e il loro numero di righe.
L'ultima riga sarà la somma delle righe di tutti i file.


Per contare tutti i file in una directory in modo ricorsivo:

Innanzitutto, abilita globstar aggiungendo shopt -s globstaral tuo .bash_profile. Il supporto per globstar richiede Bash ≥ 4.x che può essere installato con brew install bashse necessario. Puoi controllare la tua versione con bash --version.

Quindi eseguire:

wc -l **/*

Nota che questo output non sarà corretto se globstar non è abilitato.


E per contare ricorsivamente i file nella directory corrente:wc -l **/*
Taylor Edmiston

@TaylorEdmiston Per me (su Mac) che conta solo i file esattamente di una directory. Salta i file nella directory corrente, e per ogni caso che sia più di una directory in profondità avverte che è una directory: " wc: parent_dir/child_dir: read: Is a directory"
M. Justin

@Thomio Richiede abilitazione globstar. Su macOS, credo che sia disattivato e pronto all'uso. Ho appena inviato una modifica alla tua risposta che aggiunge il comando e come abilitare globstar.
Taylor Edmiston,

2

Questo comando fornirà un elenco di codici di linee in ciascuna directory:

find . -name '*.*' -type f | xargs wc -l

2

un po 'in ritardo al gioco, ma ho avuto un sacco di errori di discussione con quanto sopra a causa delle dimensioni della directory. Questo ha funzionato per me:

for i in $(find . -type f); do wc -l $i; done >> /home/counts.txt


0

catunirei i file in uno e restituire tutto allo stdout, puoi farlo wc -lsu per un conteggio totale di righe di file in una directory:

cat /path/to/directory/* | wc -l

0

Aumenterò semplicemente la risposta di @malyy per quanto segue (troppo grande per un commento):

Quante righe in totale

Molte risposte utilizzano l' wcopzione del file della riga di comando con xargs. Il problema è che xargs è limitato a una dimensione dipendente dalla piattaforma piuttosto piccola.

Inoltre c'è una differenza tra BSD (macOS) e GNU (linux / homebrew) wc.

Quello GNU è l'ideale perché può leggere l'elenco dei file da un file anziché da argomenti ( --files0).

Se sei su Mac e hai homebrew dovresti fare quanto segue:

find . -name "*.pl" -print0 | gwc -l --files0=-

Nota gwc invece di wc .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.