Yang 12Anda lihat bukan jumlah file, tetapi jumlah blok disk yang dikonsumsi.
Dari info coreutils 'ls invocation':
For each directory that is listed, preface the files with a line
`total BLOCKS', where BLOCKS is the total disk allocation for all
files in that directory. The block size currently defaults to 1024
bytes, but this can be overridden (*note Block size::). The
BLOCKS computed counts each hard link separately; this is arguably
a deficiency.
Total pergi dari 12ke 20ketika Anda menggunakan ls -labukan ls -lkarena Anda menghitung dua direktori tambahan: .dan ... Anda menggunakan empat blok disk untuk setiap direktori (kosong), sehingga total Anda berubah dari 3 × 4 hingga 5 × 4. (Dalam semua kemungkinan, Anda menggunakan satu blok disk 4096 byte untuk setiap direktori; seperti yang infoditunjukkan halaman, utilitas tidak memeriksa format disk, tetapi mengasumsikan ukuran blok 1024kecuali diperintahkan sebaliknya.)
Jika Anda hanya ingin mendapatkan jumlah file, Anda dapat mencoba sesuatu seperti
ls | wc -lakan gagal jika ada file dengan baris baru di nama file. Ini lebih tangguh:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
Flimm
20
"jika nama file memiliki baris baru di dalamnya" ... shudder
Petah
8
Seperti yang man lsakan memberitahu Anda, Anda dapat menghindari mengontrol karakter dengan -b(lolos dari mereka) atau -q(menghilangkannya). Jadi untuk penghitungan, ls -1q | wc -laman dan akurat untuk menampilkan file yang tidak tersembunyi. ls -1qA | wc -luntuk menghitung file yang tersembunyi (tetapi tidak .dan ..). Saya menggunakan -1bukan -lkarena itu harus lebih cepat.
Oli
18
user4556274 telah menjawab itu sebabnya . Jawaban saya hanya berfungsi untuk memberikan informasi tambahan tentang cara menghitung file dengan benar.
Dalam komunitas Unix, konsensus umum adalah bahwa mengurai output lsadalah ide yang sangat sangat buruk , karena nama file dapat berisi karakter kontrol atau karakter tersembunyi. Sebagai contoh, karena karakter baris baru dalam nama file, kami telah ls | wc -lmemberi tahu kami ada 5 baris dalam output ls(yang memang ada), tetapi dalam kenyataannya hanya ada 4 file dalam direktori.
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
Metode # 1: temukan utilitas
The findperintah, yang biasanya digunakan untuk bekerja di sekitar parsing nama file, dapat membantu kita di sini dengan mencetak nomor inode . Baik itu direktori atau file, itu hanya memiliki satu nomor inode unik. Dengan demikian, menggunakan -printf "%i\n"dan mengecualikan .melalui -not -name "."kami dapat memiliki jumlah file yang akurat. (Perhatikan penggunaan -maxdepth 1untuk mencegah turun secara rekursif ke dalam subdirektori)
Cara sederhana, cepat, dan sebagian besar portabel:
$ set -- *
$ echo $#
228
setperintah digunakan untuk mengatur parameter posisi shell ( $<INTEGER>variabel, seperti pada echo $1). Ini sering digunakan untuk mengatasi /bin/shketerbatasan array yang kurang. Versi yang melakukan pemeriksaan tambahan dapat ditemukan dalam jawaban Gille di Unix & Linux.
Dalam shell yang mendukung array, seperti bash, kita dapat menggunakan
Trik serupa dengan findmetode yang digunakan wcdan globstar dapat digunakan statuntuk menghitung nomor inode per baris:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Pendekatan alternatif adalah dengan menggunakan wildcard di forloop. (Catatan, tes ini menggunakan direktori yang berbeda untuk menguji apakah pendekatan ini turun ke subdirektori, yang tidak - 16 adalah jumlah item yang diverifikasi di saya ~/bin)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Metode # 3: bahasa / penerjemah lain
Python juga dapat menangani nama file yang bermasalah melalui pencetakan panjang daftar yang diberikan os.listdir()fungsi saya (yang non-rekursif, dan hanya akan mendaftar item dalam direktori yang diberikan sebagai argumen).
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
Dalam bash, opsi lain adalah menggunakan array misalnya items=( dir/* ); echo ${#items[@]}(menambahkan shopt -s dotglobuntuk menyertakan file tersembunyi).
steeldriver
1
Mencetak nomor inode memudahkan untuk memfilter hardlink jika diinginkan, dengan find | sort -u | wc -l.
Peter Cordes
@steeldriver: Saya pikir metode bash-array tidak mungkin lebih cepat. Jika Anda ingin rekursif, Anda perlu menggunakan items=( dir/** )(with shopt -s globstar), tetapi bash tidak memanfaatkan metadata tambahan dari readdir, jadi buat statistik setiap entri direktori untuk melihat apakah itu adalah direktori itu sendiri. Banyak sistem file yang menyimpan filetype dalam entri direktori, sehingga readdir dapat mengembalikannya tanpa mengakses inode. (mis. XFS non-default terbaru memiliki ini, dan saya pikir ext4 telah memilikinya lebih lama.) Jika Anda stracemenemukan, Anda akan melihat lebih sedikit statpanggilan sistem daripada mengganti bash.
Peter Cordes
2
Kenapa tidak pakai saja print(len(os.listdir('.')))? Lebih sedikit karakter untuk diketik dan juga menghindari mengakses atribut bergaris bawah dua kali lipat.
ls | wc -l
akan gagal jika ada file dengan baris baru di nama file. Ini lebih tangguh:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
man ls
akan memberitahu Anda, Anda dapat menghindari mengontrol karakter dengan-b
(lolos dari mereka) atau-q
(menghilangkannya). Jadi untuk penghitungan,ls -1q | wc -l
aman dan akurat untuk menampilkan file yang tidak tersembunyi.ls -1qA | wc -l
untuk menghitung file yang tersembunyi (tetapi tidak.
dan..
). Saya menggunakan-1
bukan-l
karena itu harus lebih cepat.user4556274 telah menjawab itu sebabnya . Jawaban saya hanya berfungsi untuk memberikan informasi tambahan tentang cara menghitung file dengan benar.
Dalam komunitas Unix, konsensus umum adalah bahwa mengurai output
ls
adalah ide yang sangat sangat buruk , karena nama file dapat berisi karakter kontrol atau karakter tersembunyi. Sebagai contoh, karena karakter baris baru dalam nama file, kami telahls | wc -l
memberi tahu kami ada 5 baris dalam outputls
(yang memang ada), tetapi dalam kenyataannya hanya ada 4 file dalam direktori.Metode # 1: temukan utilitas
The
find
perintah, yang biasanya digunakan untuk bekerja di sekitar parsing nama file, dapat membantu kita di sini dengan mencetak nomor inode . Baik itu direktori atau file, itu hanya memiliki satu nomor inode unik. Dengan demikian, menggunakan-printf "%i\n"
dan mengecualikan.
melalui-not -name "."
kami dapat memiliki jumlah file yang akurat. (Perhatikan penggunaan-maxdepth 1
untuk mencegah turun secara rekursif ke dalam subdirektori)Metode # 2: globstar
Cara sederhana, cepat, dan sebagian besar portabel:
set
perintah digunakan untuk mengatur parameter posisi shell ($<INTEGER>
variabel, seperti padaecho $1
). Ini sering digunakan untuk mengatasi/bin/sh
keterbatasan array yang kurang. Versi yang melakukan pemeriksaan tambahan dapat ditemukan dalam jawaban Gille di Unix & Linux.Dalam shell yang mendukung array, seperti
bash
, kita dapat menggunakanseperti yang diusulkan oleh steeldriver dalam komentar .
Trik serupa dengan
find
metode yang digunakanwc
dan globstar dapat digunakanstat
untuk menghitung nomor inode per baris:Pendekatan alternatif adalah dengan menggunakan wildcard di
for
loop. (Catatan, tes ini menggunakan direktori yang berbeda untuk menguji apakah pendekatan ini turun ke subdirektori, yang tidak - 16 adalah jumlah item yang diverifikasi di saya~/bin
)Metode # 3: bahasa / penerjemah lain
Python juga dapat menangani nama file yang bermasalah melalui pencetakan panjang daftar yang diberikan
os.listdir()
fungsi saya (yang non-rekursif, dan hanya akan mendaftar item dalam direktori yang diberikan sebagai argumen).Lihat juga
sumber
items=( dir/* ); echo ${#items[@]}
(menambahkanshopt -s dotglob
untuk menyertakan file tersembunyi).find | sort -u | wc -l
.items=( dir/** )
(withshopt -s globstar
), tetapi bash tidak memanfaatkan metadata tambahan dari readdir, jadi buat statistik setiap entri direktori untuk melihat apakah itu adalah direktori itu sendiri. Banyak sistem file yang menyimpan filetype dalam entri direktori, sehingga readdir dapat mengembalikannya tanpa mengakses inode. (mis. XFS non-default terbaru memiliki ini, dan saya pikir ext4 telah memilikinya lebih lama.) Jika Andastrace
menemukan, Anda akan melihat lebih sedikitstat
panggilan sistem daripada mengganti bash.print(len(os.listdir('.')))
? Lebih sedikit karakter untuk diketik dan juga menghindari mengakses atribut bergaris bawah dua kali lipat.