user4556274 ha già risposto al perché . La mia risposta serve solo a fornire ulteriori informazioni su come contare correttamente i file.
Nella comunità Unix il consenso generale è che l' analisi dell'output di ls
è una pessima idea , dal momento che i nomi dei file possono contenere caratteri di controllo o caratteri nascosti. Ad esempio, a causa di un carattere di nuova riga in un nome file, abbiamo ls | wc -l
detto che ci sono 5 righe nell'output di ls
(che ha), ma in realtà ci sono solo 4 file nella directory.
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
Metodo n. 1: trova utilità
Il find
comando, che in genere viene utilizzato per aggirare l'analisi dei nomi dei file, può aiutarci qui stampando il numero dell'inode . Che si tratti di una directory o di un file, ha solo un numero di inode univoco. Pertanto, usando -printf "%i\n"
ed escludendo .
via -not -name "."
possiamo avere un conteggio accurato dei file. (Notare l'uso di -maxdepth 1
per impedire la discesa ricorsiva nelle sottodirectory)
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
Metodo n. 2: globstar
Modo semplice, rapido e per lo più portatile:
$ set -- *
$ echo $#
228
set
Il comando viene utilizzato per impostare i parametri posizionali della shell (le $<INTEGER>
variabili, come in echo $1
). Questo è spesso usato per aggirare la /bin/sh
limitazione delle matrici mancanti. Una versione che esegue controlli extra può essere trovata nella risposta di Gille su Unix e Linux.
In shell che supportano array, come ad esempio bash
, possiamo usare
items=( dir/* )
echo ${#items[@]}
come proposto da steeldriver nei commenti .
Trucco simile al find
metodo utilizzato wc
e globstar con cui stat
poter contare i numeri di inode per riga:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Un approccio alternativo consiste nell'utilizzare un carattere jolly in for
loop. (Nota, questo test utilizza una directory diversa per verificare se questo approccio scende nelle sottodirectory, che non ha - 16 è il numero verificato di elementi nel mio ~/bin
)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Metodo n. 3: altre lingue / interpreti
Python può anche gestire nomi di file problematici stampando la lunghezza di un elenco dato la mia os.listdir()
funzione (che non è ricorsiva e elencherà solo gli elementi nella directory indicati come argomento).
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
Guarda anche
ls | wc -l
fallirà se ci sono file con una nuova riga nel nome del file. Questo è più resistente:find . -mindepth 1 -maxdepth 1 -printf . | wc -c