Come posso ottenere un conteggio dei file in una directory usando la riga di comando?


Risposte:


239

Utilizzando un'ampia definizione di "file"

ls | wc -l

(nota che non conta i file nascosti e presuppone che i nomi dei file non contengano caratteri di nuova riga).

Per includere file nascosti (tranne .e ..) ed evitare problemi con i caratteri di nuova riga, il modo canonico è:

find . ! -name . -prune -print | grep -c /

O ricorsivamente:

find .//. ! -name . -print | grep -c //

23
wcè un programma "conteggio parole". Lo -lswitch provoca il conteggio delle righe. In questo caso, sta contando le righe nell'output da ls. Questo è sempre il modo in cui mi è stato insegnato di ottenere un conteggio dei file anche per una determinata directory.
Sandy,

20
si prega di aggiungere nota che lo lsfa ls -1se l'output è una pipe.
lesmana,

6
che non contiene tutto in una directory: hai perso i file dot e colleziona anche un paio di righe extra. Una directory vuota restituirà comunque 1 riga. E se chiami ls -la, otterrai tre linee nella rubrica. Si desidera ls -lA | wc -lsaltare le voci .e ... Sarai comunque off-by-one, comunque.

1
Una directory vuota restituisce 0 per me
James Roth,

2
Un approccio corretto, che non farebbe il doppio conteggio dei file con nuove righe nel nome, sarebbe questo: ls -q | wc -l- sebbene si noti che i file nascosti non verranno comunque conteggiati da questo approccio e che le directory verranno conteggiate.
godlygeek

31

Per una definizione ristretta del file:

 find . -maxdepth 1 -type f | wc -l

E puoi ovviamente omettere il -maxdepth 1conteggio dei file in modo ricorsivo (o modificarlo per la profondità di ricerca massima desiderata).
user7089

1
Se si dispone di un file il cui nome contiene una nuova riga, questo approccio lo conteggerà erroneamente due volte.
godlygeek

7
Un approccio corretto, che non farebbe il doppio conteggio dei file con nuove righe nel nome, sarebbe questo:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek

+1 Consenti file nascosti e ignora le directory
Michael Durrant,

14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: Nota ls - <number-one> | wc - <letter-l>


10
La maggior parte delle versioni di lsfa -1automaticamente quando l'output è su una pipe.
Dennis Williamson,

3
@Dennis è interessante, non sapevo che un'applicazione potesse dire che il suo output sarebbe andato a finire.
xenoterracide,

1
Ho scritto questa versione poiché è più esplicita. Tuttavia, sì ls usa -1 se è convogliato (provalo: ls | cat), trovo la sintassi -1 più esplicita.
gabe.

3
@xenoterracide: In Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson,

2
Nei miei test è stato significativamente più veloce fornire anche l'opzione -f per evitare che ordinassi i nomi dei file. Sfortunatamente hai ancora la risposta sbagliata se i tuoi nomi di file contengono nuove righe.
Samuel Edwin Ward

10

Probabilmente la risposta più completa usando ls/ wcpair è

ls -Aq | wc -l

se si desidera contare i file di punti e

ls -q | wc -l

altrimenti.

  • -Aè contare i file dot, ma omettere .e ...
  • -qmake lssostituisce i caratteri non grafici, in particolare il carattere di nuova riga, con ?, creando 1 riga di output per ogni file

Per ottenere un output di una riga dal lsterminale (ovvero senza collegarlo a wc), -1è necessario aggiungere l'opzione.

(comportamento del lstestato con coreutils 8.23)


2
Come hai detto, -1non è necessario. Quanto a "gestisce le nuove righe in nomi di file in modo sensibile con l'output della console" , ciò è dovuto allo -qswitch (che dovresti usare invece che -bperché è portatile) che "Forza ogni istanza di caratteri di file non stampabili e <tab> da scrivere come carattere <question-mark> ('?'). Le implementazioni possono fornire questa opzione per impostazione predefinita se l'output è destinato a un dispositivo terminale. " Ad esempio, ls -Aq | wc -lper contare tutti i file / directory o ls -qp | grep -c /contare solo le directory non nascoste, ecc ...
don_crissti,

Grazie per il tuo contributo. Modificato -bin -q.
Frax,

7

Se conosci la directory corrente contiene almeno un file non nascosto:

set -- *; echo "$#"

Questo è ovviamente generalizzabile per qualsiasi glob.

In una sceneggiatura, questo ha l'effetto collaterale a volte sfavorevole di sovrascrivere i parametri posizionali. È possibile aggirare ciò utilizzando una subshell o con una funzione (versione Bourne / POSIX) come:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Una soluzione alternativa è $(ls -d -- * | wc -l). Se il glob è *, il comando può essere abbreviato in $(ls | wc -l). Analizzare l'output di lsmi fa sempre sentire a disagio, ma qui dovrebbe funzionare fintanto che i nomi dei tuoi file non contengono nuove righe o le lselimini. E $(ls -d -- * 2>/dev/null | wc -l)ha il vantaggio di gestire il caso di un glob non corrispondente con garbo (cioè, restituisce 0 in quel caso, mentre il set *metodo richiede test complicati se il glob potrebbe essere vuoto).

Se i nomi dei file possono contenere caratteri di nuova riga, utilizzare un'alternativa $(ls -d ./* | grep -c /).

Qualsiasi di quelle soluzioni che fanno affidamento sul passaggio dell'espansione di un glob lspotrebbe non riuscire con un errore troppo lungo nella lista degli argomenti se ci sono molti file corrispondenti.


1
Vuoi davvero creare 13.923 parametri posizionali? E dovresti rendere la tua variabile locale localo eliminarla: eval $1=$#o semplicemente usare echo $#e fare number_of_files=$(count_words *).
Dennis Williamson,

1
@Dennis: parte del punto era evitare il biforcazione. Immagino che non sia una preoccupazione del 21 ° secolo. Ok, ammetto che non mi importa più delle shell non POSIX, quindi avrei potuto evitare la variabile temporanea.
Gilles,

Perché ne hai sottratto uno $#(non l'avevi fatto prima della modifica)?
Dennis Williamson,

@Dennis: sto ancora evitando un fork (beh, fa la differenza su macchine con una CPU lenta come i router) e passa un nome variabile come $1. Quindi quello che voglio contare è il numero di parametri che non sono il primo parametro. (Non posso usarlo shiftperché devo mantenere il nome della variabile in giro.) (Umm, ora se avessi chiesto della prima riga ...)
Gilles

@Dennis: vieni a pensarci bene, posso usarlo shiftse ho il tempo giusto.
Gilles,

7

Ho trovato du --inodesutile, ma non sono sicuro di quale versione durichieda. Dovrebbe essere sostanzialmente più veloce di approcci alternativi usando finde wc.

Su Ubuntu 17.10, funziona come segue:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Combina con | sort -nrper ordinare in ordine decrescente per numero di inode contenenti.


5

Durante l'utilizzo della coppia ls / wc se stiamo aggiungendo -U sarà molto più veloce (non ordinare).

ls -AqU | wc -l

1
-Uè specifico di GNU però.
Stéphane Chazelas,

4

Dopo aver installato il comando tree, basta digitare:

tree

Se vuoi anche file nascosti:

tree -a

Se stai usando Debian / Mint / Ubuntu Linux, digita il seguente comando per installare il comando tree:

sudo apt-get install tree

L'opzione -L viene utilizzata per specificare il livello massimo di visualizzazione dell'albero delle directory. Il comando tree non conta solo il numero di file, ma anche il numero di directory, considerando tutti i livelli dell'albero di directory che desideri.


Quando scrivo albero, ottengo una sorta di output dell'albero sullo schermo della directory in cui mi trovo ma non riesco a vedere dove viene mostrato il numero di file.
charlesdarwin,

2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1lo renderà non ricorsivo, findè ricorsivo per impostazione predefinita
  • -type f includerà solo i file
  • -printf .è un tocco carino. stampa un punto per ciascun file anziché il nome file, e ora è in grado di gestire qualsiasi nome file e salva anche i dati; non ci resta che contare i punti :)
  • | wc -c conta i personaggi

1

Nessuna pipa, nessuna copia di stringa, nessuna forchetta, solo una riga di base

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount

1
Fornisce un valore 1 se non ci sono file nella directory. Non conta i file, conta i file e le directory.
steve

1

Ecco un'altra tecnica sulla falsariga di quella pubblicata da Gilles :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

che crea un array con 13.923 elementi (se sono quanti file ci sono).


Qual è il punto di quell'array c? word_count() { echo "$#"; }sarebbe abbastanza. Il punto della soluzione @Gilles è di archiviare il conteggio in una variabile restituita per evitare di dover usare la sostituzione dei comandi (che implica un fork e un pipe in shell diverse da ksh93).
Stéphane Chazelas,

1
find . -type f -maxdepth 1 |  wc -l 

Questo può elencare solo i file nella directory corrente.


find . -type ftroverà i file nella directory corrente e anche, ricorsivamente, nelle sottodirectory.
dhag,

0

Prova questo spero che questa risposta ti possa aiutare

echo $((`ls -l | wc -l` -1 ))


0

Migliorare alcune risposte fornite prima, ma questa volta facendo esplicitamente.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

È degno di nota l'uso di alcuni comandi amati come taile cut. Inoltre, tieni presente che l'albero non è disponibile per impostazione predefinita. Il comando sopra prima acquisisce informazioni sulla directory al livello 1, quindi ottiene l'ultima riga in tail -n 1cui è il nostro obiettivo e finisce cutper prendere la terza parola.

Ad esempio, individuando in /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Quindi, che ne dici di chiedere il numero di directory?


0

Su Linux, per rendere il comando molto robusto e gestire i file che potrebbero avere nuove righe nel loro nome, utilizzare questo:

find -maxdepth 1 -type f -print0 | tr -cd '\0' | wc -c

Questo ci salva dalla prova del parsing lsdell'output.


Relazionato:


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.