Jawaban singkat:
\ls -afq | wc -l
(Ini termasuk .
dan ..
, jadi kurangi 2.)
Ketika Anda mendaftar file dalam direktori, tiga hal umum mungkin terjadi:
- Menghitung nama file dalam direktori. Ini tidak bisa dihindari: tidak ada cara untuk menghitung file dalam direktori tanpa menyebutkannya.
- Menyortir nama file. Shell wildcard dan
ls
perintah melakukan itu.
- Memanggil
stat
untuk mengambil metadata tentang setiap entri direktori, seperti apakah itu direktori.
# 3 adalah yang paling mahal sejauh ini, karena membutuhkan memuat inode untuk setiap file. Sebagai perbandingan, semua nama file yang diperlukan untuk # 1 disimpan secara kompak dalam beberapa blok. # 2 membuang-buang waktu CPU tetapi sering kali bukan pemecah kesepakatan.
Jika tidak ada baris baru dalam nama file, sederhana akan ls -A | wc -l
memberi tahu Anda berapa banyak file yang ada di direktori. Hati-hati bahwa jika Anda memiliki alias untuk ls
, ini dapat memicu panggilan ke stat
(mis. ls --color
Atau ls -F
perlu mengetahui jenis file, yang membutuhkan panggilan ke stat
), jadi dari baris perintah, panggil command ls -A | wc -l
atau \ls -A | wc -l
untuk menghindari alias.
Jika ada baris baru dalam nama file, apakah baris baru terdaftar atau tidak tergantung pada varian Unix. GNU coreutils dan BusyBox default untuk ditampilkan ?
untuk baris baru, jadi mereka aman.
Panggil ls -f
untuk mendaftar entri tanpa menyortirnya (# 2). Ini secara otomatis menyala -a
(setidaknya pada sistem modern). The -f
pilihan adalah di POSIX tapi dengan status yang opsional; sebagian besar implementasi mendukungnya, tetapi tidak BusyBox. Opsi ini -q
menggantikan karakter yang tidak dapat dicetak termasuk baris baru dengan ?
; itu POSIX tetapi tidak didukung oleh BusyBox, jadi abaikan saja jika Anda memerlukan dukungan BusyBox dengan mengorbankan overcounting file yang namanya berisi karakter baris baru.
Jika direktori tidak memiliki subdirektori, maka sebagian besar versi find
tidak akan memanggil stat
entri-entrinya (optimisasi direktori daun: direktori yang memiliki jumlah tautan 2 tidak dapat memiliki subdirektori, jadi find
tidak perlu mencari metadata entri kecuali jika kondisi seperti -type
membutuhkannya). Begitu find . | wc -l
juga cara portabel dan cepat untuk menghitung file dalam direktori asalkan direktori tersebut tidak memiliki subdirektori dan bahwa tidak ada nama file yang mengandung baris baru.
Jika direktori tidak memiliki subdirektori tetapi nama file mungkin mengandung baris baru, coba salah satu dari ini (yang kedua harus lebih cepat jika didukung, tetapi mungkin tidak begitu terlihat).
find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c
Di sisi lain, jangan gunakan find
jika direktori memiliki subdirektori: bahkan find . -maxdepth 1
panggilan stat
pada setiap entri (setidaknya dengan GNU find dan BusyBox find). Anda menghindari penyortiran (# 2) tetapi Anda membayar harga pencarian inode (# 3) yang membunuh kinerja.
Dalam shell tanpa alat eksternal, Anda dapat menjalankan menghitung file dalam direktori saat ini set -- *; echo $#
. Ini melewatkan file dot (file yang namanya dimulai dengan .
) dan melaporkan 1 bukannya 0 di direktori kosong. Ini adalah cara tercepat untuk menghitung file dalam direktori kecil karena tidak memerlukan memulai program eksternal, tetapi (kecuali dalam zsh) membuang waktu untuk direktori yang lebih besar karena langkah penyortiran (# 2).
Dalam bash, ini adalah cara yang dapat diandalkan untuk menghitung file di direktori saat ini:
shopt -s dotglob nullglob
a=(*)
echo ${#a[@]}
Di ksh93, ini adalah cara yang dapat diandalkan untuk menghitung file di direktori saat ini:
FIGNORE='@(.|..)'
a=(~(N)*)
echo ${#a[@]}
Di zsh, ini adalah cara yang dapat diandalkan untuk menghitung file di direktori saat ini:
a=(*(DNoN))
echo $#a
Jika Anda memiliki mark_dirs
pilihan set, pastikan untuk mematikannya: a=(*(DNoN^M))
.
Di setiap shell POSIX, ini adalah cara yang dapat diandalkan untuk menghitung file di direktori saat ini:
total=0
set -- *
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- .[!.]*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- ..?*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
echo "$total"
Semua metode ini mengurutkan nama file, kecuali untuk yang zsh.
ls -l|wc -l
akan dimatikan satu per satu karena total blok pada baris pertamals -l
keluaran