Menghitung baris kode?

24

jika saya ingin menghitung baris kode, hal yang sepele adalah

cat *.c *.h | wc -l

Tetapi bagaimana jika saya memiliki beberapa subdirektori?

Niklas
sumber
3
Di luar topik: Mengapa tidak perlu cat? wc -l *.c *.hmelakukan hal yang sama.
Thomas Padron-McCarthy
5
@ ThomasPadron-McCarthy Tidak, tidak. Anda harus wc -l *.c *.h | tail -n 1mendapatkan hasil yang serupa.
Gilles 'SO- berhenti menjadi jahat'
2
Perhatikan bahwa beberapa (mungkin bahkan sebagian besar) shell modern (Bash v4, Zsh, mungkin lebih) menyediakan mekanisme globbing rekursif menggunakan **, sehingga Anda bisa menggunakan wc -l **/*.{h,c}atau sesuatu yang serupa. Perhatikan bahwa dalam Bash, setidaknya, opsi ini (dipanggil globstar) tidak aktif secara default. Tetapi juga perhatikan bahwa dalam kasus khusus ini, clocatau SLOCCountmerupakan pilihan yang jauh lebih baik. (Juga, ackmungkin lebih disukai finduntuk mencari / mendaftar file sumber dengan mudah.)
Kyle Strand
5
wc-l menghitung baris, bukan baris kode. 7000 baris kosong masih akan muncul di wc -l tetapi tidak akan dihitung dalam metrik kode. (komentar juga biasanya tidak masuk hitungan)
coteyr

Jawaban:

49

Cara termudah adalah dengan menggunakan alat yang disebut cloc. Gunakan seperti ini:

cloc .

Itu dia. :-)

Ho1
sumber
1
-1 karena program ini tidak memiliki cara untuk mengenali baris kode dalam bahasa di luar otaknya yang kecil dan membosankan. Ia tahu tentang Ada dan Pascal dan C dan C ++ dan Java dan JavaScript dan bahasa jenis "perusahaan", tetapi menolak untuk menghitung SLOC hanya dengan ekstensi file, dan karenanya sama sekali tidak berguna untuk DSL, atau bahkan bahasa yang kebetulan tidak diketahui tentang.
kucing
21
@cat Tidak ada yang sempurna, dan tidak ada yang bisa memenuhi semua tuntutan masa lalu dan masa depan Anda.
Ho1
2
Ya, bahasa pemrograman yang CLOC tolak untuk mengakui memang memenuhi semua tuntutan masa lalu dan masa depan saya :)
cat
6
@cat menurut dokumentasi CLOC dapat dibaca dalam file definisi bahasa, jadi ada cara untuk mendapatkannya untuk mengenali kode dalam bahasa yang belum didefinisikan. Plus itu open source, jadi Anda selalu dapat memperluasnya untuk membuatnya lebih baik!
Centimane
39

Anda mungkin harus menggunakan SLOCCount atau cloc untuk ini, mereka dirancang khusus untuk menghitung baris kode sumber dalam suatu proyek, terlepas dari struktur direktori dll .; antara

sloccount .

atau

cloc .

akan menghasilkan laporan tentang semua kode sumber mulai dari direktori saat ini.

Jika Anda ingin menggunakan finddan wc, GNU wcmemiliki --files0-fromopsi yang bagus :

find . -name '*.[ch]' -print0 | wc --files0-from=-

(Terima kasih kepada SnakeDoc untuk saran cloc !)

Stephen Kitt
sumber
+1 untuk sloccount. Menariknya, menjalankan sloccount /tmp/stackexchange(dibuat lagi pada 17 Mei setelah reboot terbaru saya) mengatakan bahwa perkiraan biaya untuk mengembangkan file sh, perl, awk, dll itu ditemukan adalah $ 11.029. dan itu tidak termasuk one-liner yang tidak pernah membuatnya menjadi file skrip.
cas
11
Memperkirakan biaya berdasarkan garis kode? Bagaimana dengan semua orang yang dipekerjakan untuk memasukkan faktor spaghetti menjadi sesuatu yang bisa dipertahankan?
Stop Harming Monica
@OrangeDog Anda selalu dapat mencoba memperhitungkannya di overhead; lihat dokumentasi untuk penjelasan perhitungan (dengan data gaji yang sangat lama) dan parameter yang dapat Anda atur.
Stephen Kitt
5
clocjuga bagus: github.com/AlDanial/cloc
SnakeDoc
@StephenKitt> masih, masalah utamanya adalah menghitung mundur. Saat membersihkan kode, Anda sering berakhir dengan lebih sedikit garis. Tentu Anda dapat mencoba untuk menggunakan gelombang tangan untuk mengeluarkan sisa kode untuk memperhitungkan yang dihapus, tapi saya tidak melihat bagaimana itu lebih baik daripada hanya menebak seluruh harga di tempat pertama.
spektrum
10

Karena wcperintah dapat mengambil banyak argumen, Anda bisa meneruskan semua nama file untuk wcmenggunakan +argumen -exectindakan GNU find:

find . -type f -name '*.[ch]' -exec wc -l {} +

Bergantian, dalam bash, menggunakan opsi shell globstaruntuk menelusuri direktori secara rekursif:

shopt -s globstar
wc -l **/*.[ch]

Kerang lain melintasi secara rekursif secara default (misalnya zsh) atau memiliki opsi serupa seperti globstar, paling tidak sebagian besar.

heemayl
sumber
1
+1 karena tidak perlu menginstal perangkat lunak non-standar pada mesin di mana saya tidak memiliki root
Bamboomy
5

Anda dapat menggunakannya findbersama dengan xargsdan wc:

find . -type f -name '*.h' -o -name '*.c' | xargs wc -l
coffeMug
sumber
2
(yang mengasumsikan jalur file tidak mengandung kosong, baris baru, kutipan tunggal, kutipan ganda karakter backslash. Mungkin juga menampilkan beberapa totalbaris jika beberapa wcsedang dipanggil.)
Stéphane Chazelas
Mungkin masalah beberapa wcperintah dapat diatasi dengan perpipaan findke while read FILENAME; do . . .donestruktur. Dan di dalam penggunaan while wc -l. Sisanya menjumlahkan garis total menjadi variabel dan menampilkannya.
Sergiy Kolodyazhnyy
5

Jika Anda berada di lingkungan di mana Anda tidak memiliki akses ke clocdll saya sarankan

find -name '*.[ch]' -type f -exec cat '{}' + | grep -c '[^[:space:]]'

Run-through: findmencari secara rekursif untuk semua file biasa yang namanya berakhir dengan salah .catau .hdan menjalankannya cat. Output disalurkan melalui grepuntuk menghitung semua baris non-kosong (yang berisi setidaknya satu karakter non-spasi).

Kotte
sumber
4

Seperti telah ditunjukkan di komentar, cat file | wc -lini tidak setara dengan wc -l filekarena mantan mencetak hanya sejumlah sedangkan cetakan kedua nomor dan nama file. Demikian juga cat * | wc -lakan mencetak hanya angka, sedangkan wc -l *akan mencetak garis informasi untuk setiap file.

Dalam semangat kesederhanaan, mari kita kembali ke pertanyaan yang sebenarnya ditanyakan:

jika saya ingin menghitung baris kode, hal yang sepele adalah

cat *.c *.h | wc -l

Tetapi bagaimana jika saya memiliki beberapa subdirektori?

Pertama, Anda bahkan dapat menyederhanakan perintah sepele Anda menjadi:

cat *.[ch] | wc -l

Dan akhirnya, banyak-subdirektori yang setara adalah:

find . -name '*.[ch]' -exec cat {} + | wc -l

Ini mungkin dapat ditingkatkan dengan banyak cara, seperti membatasi file yang cocok hanya file biasa (bukan direktori) dengan menambahkan -type f— tetapi findperintah yang diberikan adalah setara rekursif yang tepatcat *.[ch] .

Wildcard
sumber
3

Sampel menggunakan awk:

find . -name '*.[ch]' -exec wc -l {} \; |
  awk '{SUM+=$1}; END { print "Total number of lines: " SUM }'
Lambert
sumber
Gunakan +di tempat \;.
Jonathan Leffler
@JonathanLeffler Mengapa?
Hastur,
1
@ Rushur: Ini berjalan wc -luntuk kelompok file, lebih tepatnya seperti xargstidak, tetapi menangani karakter aneh-bola (seperti spasi) dalam nama file tanpa perlu salah satu xargsatau (non-standar) -print0dan -0opsi untuk finddan xargsmasing - masing. Ini optimasi kecil. Kelemahannya adalah bahwa setiap doa wcakan menghasilkan jumlah baris total pada akhir ketika diberikan banyak file - awkskrip akan berurusan dengan itu. Jadi, ini bukan slam-dunk, tetapi sangat sering, menggunakan +di tempat \;dengan findadalah ide yang bagus.
Jonathan Leffler
@JonathanLeffler Terima kasih. Saya setuju. Kekhawatiran saya, bagaimanapun, adalah tentang panjang string parameter yang diteruskan wc. Jika tidak diketahui apriori jumlah file yang akan ditemukan , apakah ada risiko untuk melewati batas itu atau entah bagaimana itu ditangani oleh find?
Hastur,
2
@Hastur: findmengelompokkan file ke dalam bundel ukuran yang nyaman, yang tidak akan melebihi batas panjang untuk daftar argumen pada platform, memungkinkan untuk lingkungan (yang keluar dari panjang daftar argumen - sehingga panjang daftar argumen ditambah dengan panjang lingkungan harus kurang dari nilai maksimum). TKI, findmelakukan pekerjaan dengan benar, seperti xargsmelakukan pekerjaan dengan benar.
Jonathan Leffler
1

perintah mudah:

find . -name '*.[ch]' | xargs wc -l
malyy
sumber
(yang mengasumsikan jalur file tidak mengandung kosong, baris baru, kutipan tunggal, kutipan ganda karakter backslash. Mungkin juga menampilkan beberapa totalbaris jika beberapa wcsedang dipanggil.)
Stéphane Chazelas
0

Jika Anda menggunakan Linux, saya merekomendasikan alat saya sendiri, polyglot . Ini secara dramatis lebih cepat daripada clocdan lebih fitur daripada sloccount.

Anda harus dapat membangun BSD juga, meskipun tidak ada binari yang disediakan.

Anda dapat memohonnya dengan

poly .

sumber
-2

find . -name \*.[ch] -print | xargs -n 1 wc -lharus melakukan trik. Ada beberapa variasi yang mungkin mengenai hal itu juga, seperti menggunakan -execalih-alih menyalurkan output ke wc.

John
sumber
4
Tetapi find . -name \*.[ch] -printtidak mencetak isi file, hanya nama file. Jadi saya menghitung jumlah file bukan? Apakah saya perlu `xargs '?
Niklas
@ Programmer400 ya, Anda akan perlu xargs, dan Anda juga harus menonton untuk beberapa wcpermintaan jika Anda memiliki banyak file; Anda harus mencari semua totalgaris dan menjumlahkannya.
Stephen Kitt
Jika Anda hanya ingin jumlah baris total, Anda perlu melakukannyafind . -name \*.[ch] -print0 | xargs -0 cat | wc -l
fluffy
Perhatikan bahwa ini ( find . -name \*.[ch] -print | wc -l) menghitung jumlah file (kecuali nama file berisi baris baru - tapi itu sangat tidak biasa) - ini tidak menghitung jumlah baris dalam file.
Jonathan Leffler