Pertanyaan Apakah ada perintah bash yang menghitung file?


Apakah ada perintah bash yang menghitung jumlah file yang sesuai dengan pola?

Sebagai contoh, saya ingin mendapatkan hitungan semua file dalam direktori yang cocok dengan pola ini: log*


75
2017-07-03 08:35


asal


Jawaban:


Alat satu baris sederhana ini dapat digunakan di shell mana pun, tidak hanya bash:

ls -1q log* | wc -l

ls -1q akan memberi Anda satu baris per file, meskipun berisi spasi putih atau karakter khusus seperti baris baru.

Output disalurkan ke wc -l, yang menghitung jumlah baris.


101
2017-07-03 08:41



Anda dapat melakukannya dengan aman (mis. Tidak akan disadap file dengan spasi atau \n atas nama mereka) dengan bash:

$ shopt -s nullglob
$ logfiles=(*.log)
$ echo ${#logfiles[@]}
$ shopt -u nullglob

Anda harus mengaktifkan nullglob sehingga Anda tidak mengerti secara harfiah *.log dalam $logfiles  larik jika tidak ada file yang cocok.


33
2017-07-03 08:43



Coba ini:

echo *.log | wc -w


30
2017-07-03 08:41



Banyak jawaban di sini, tetapi beberapa tidak memperhitungkannya

  • nama file dengan spasi, baris baru, atau karakter kontrol di dalamnya
  • nama file yang dimulai dengan tanda hubung (bayangkan sebuah file bernama -l)
  • direktori kosong (yaitu hasilnya 0)
  • direktori yang sangat besar (daftar semuanya bisa menghabiskan memori)

Berikut ini solusi yang menangani semuanya:

ls 2>/dev/null -Ub1 -- log* | wc -l

Penjelasan:

  • -U penyebab ls untuk tidak mengurutkan entri, yang berarti tidak perlu memuat seluruh daftar direktori di memori
  • -b mencetak pelolosan C-style untuk karakter nongraphic, yang secara krusial menyebabkan baris baru untuk dicetak sebagai \n.
  • 2>/dev/null redirects stderr sehingga jika ada 0 file log, abaikan pesan kesalahan. (Perhatikan itu shopt -s nullglob akan menyebabkan ls untuk daftar seluruh direktori kerja.)
  • wc -l mengkonsumsi daftar direktori seperti yang sedang dihasilkan, jadi output dari ls tidak pernah dalam memori pada suatu titik waktu.
  • -- Nama file dipisahkan dari perintah yang digunakan -- agar tidak dipahami sebagai argumen untuk ls (dalam hal log* dihapus)

Kerang akan memperluas log* ke daftar lengkap file, yang mungkin menghabiskan memori jika banyak file, sehingga kemudian menjalankannya melalui grep lebih baik:

ls -Ub1 | grep ^log | wc -l

Yang terakhir ini menangani direktori file yang sangat besar tanpa menggunakan banyak memori (meskipun ia menggunakan subkulit).


28
2017-11-24 11:01



Jawaban yang diterima untuk pertanyaan ini salah, tetapi saya memiliki perwakilan rendah sehingga tidak dapat menambahkan komentar untuk itu.

Jawaban yang benar untuk pertanyaan ini diberikan oleh Mat:

shopt -s nullglob
logfiles=(*.log)
echo ${#logfiles[@]}

Masalah dengan jawaban yang diterima adalah bahwa wc-l menghitung jumlah karakter baris baru, dan menghitungnya bahkan jika mereka mencetak ke terminal sebagai '?' dalam output 'ls-l'. Ini berarti bahwa jawaban yang diterima GAGAL ketika nama file berisi karakter baris baru. Saya telah menguji perintah yang disarankan:

ls -l log* | wc -l

dan secara keliru melaporkan nilai 2 bahkan jika hanya ada 1 file yang cocok dengan pola yang namanya kebetulan mengandung karakter baris baru. Sebagai contoh:

touch log$'\n'def
ls log* -l | wc -l

5
2017-10-30 06:11



Jika Anda memiliki banyak file dan Anda tidak ingin menggunakan yang elegan shopt -s nullglob dan solusi bash array, Anda dapat menggunakan find dan seterusnya selama Anda tidak mencetak nama file (yang mungkin berisi baris baru).

find -maxdepth 1 -name "log*" -not -name ".*" -printf '%i\n' | wc -l

Ini akan menemukan semua file yang cocok dengan log * dan yang tidak dimulai dengan .* - "Bukan nama. *" Redunant, tetapi penting untuk dicatat bahwa default untuk "ls" adalah untuk tidak menampilkan file-file dot, tetapi default untuk find adalah menyertakannya.

Ini adalah jawaban yang benar, dan menangani semua jenis nama file yang dapat Anda lempar padanya, karena nama file tidak pernah dibagikan di antara perintah.

Tetapi shopt nullglob Jawabannya adalah jawaban terbaik!


4
2017-08-22 19:16



Ini adalah satu liner saya untuk ini.

 file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)

2
2017-11-04 19:48



ls -1 log* | wc -l

Yang berarti mencantumkan satu file per baris dan kemudian menyalurkannya ke perintah hitungan kata dengan peralihan parameter untuk menghitung garis.


1
2017-07-03 20:17