Đếm các dòng mã?


24

Nếu tôi muốn đếm các dòng mã, điều tầm thường là

cat *.c *.h | wc -l

Nhưng nếu tôi có một vài thư mục con thì sao?



3
Off-topic: Tại sao không cần thiết cat? wc -l *.c *.hlàm điều tương tự
Thomas Padron-McCarthy

5
@ ThomasPadron-McCarthy Không, không. Bạn sẽ cần wc -l *.c *.h | tail -n 1nhận được đầu ra tương tự.
Gilles 'SO- đừng trở nên xấu xa'

2
Lưu ý rằng một số (hiện tại thậm chí là hầu hết) các shell hiện đại (Bash v4, Zsh, có thể nhiều hơn) cung cấp một cơ chế tạo đệ quy sử dụng **, do đó bạn có thể đã sử dụng wc -l **/*.{h,c}hoặc một cái gì đó tương tự. Lưu ý rằng trong Bash, ít nhất, tùy chọn này (được gọi globstar) bị tắt theo mặc định. Nhưng cũng lưu ý rằng trong trường hợp cụ thể này, clochoặc SLOCCountlà một lựa chọn tốt hơn nhiều. (Ngoài ra, ackcó thể thích hợp hơn để finddễ dàng tìm / liệt kê các tệp nguồn.)
Kyle Strand

5
wc -l đếm các dòng, không phải các dòng mã. 7000 dòng trống sẽ vẫn hiển thị trong wc -l nhưng sẽ không được tính vào một số liệu mã. (bình luận quá thường không được tính)
coteyr

Câu trả lời:


49

Cách dễ nhất là sử dụng công cụ được gọi là cloc. Sử dụng theo cách này:

cloc .

Đó là nó. :-)


1
-1 bởi vì chương trình này không có cách nào để nhận ra các dòng mã bằng các ngôn ngữ bên ngoài bộ não nhỏ bé, nhàm chán của nó. Nó biết về Ada và Pascal và C và C ++, Java và JavaScript và các ngôn ngữ loại "doanh nghiệp", nhưng nó từ chối đếm SLOC chỉ bằng cách mở rộng tệp và do đó hoàn toàn vô dụng đối với DSL hoặc thậm chí các ngôn ngữ mà nó không biết trong khoảng.
mèo

21
@cat Không có gì là hoàn hảo, và không có gì có thể đáp ứng tất cả các nhu cầu trong quá khứ và tương lai của bạn.
Ho1

2
Chà, ngôn ngữ lập trình mà CLOC từ chối thừa nhận thực sự đáp ứng tất cả các nhu cầu trong quá khứ và tương lai của tôi :)
mèo

6
@cat theo tài liệu CLOC nó có thể đọc trong tệp định nghĩa ngôn ngữ, vì vậy có một cách để khiến nó nhận ra mã bằng các ngôn ngữ mà nó chưa được xác định. Thêm vào đó là nguồn mở, vì vậy bạn luôn có thể mở rộng nó để làm cho nó tốt hơn!
Centimane

39

Bạn có thể nên sử dụng SLOCCount hoặc cloc cho việc này, chúng được thiết kế đặc biệt để đếm các dòng mã nguồn trong một dự án, bất kể cấu trúc thư mục, v.v.; hoặc

sloccount .

hoặc là

cloc .

sẽ tạo một báo cáo về tất cả các mã nguồn bắt đầu từ thư mục hiện tại.

Nếu bạn muốn sử dụng findwc, GNU wccó một --files0-fromtùy chọn hay:

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

(Cảm ơn SnakeDoc về đề xuất cloc !)


+1 cho sloccount. Thật thú vị, chạy sloccount /tmp/stackexchange(được tạo lại vào ngày 17 tháng 5 sau lần khởi động lại gần đây nhất của tôi) nói rằng chi phí ước tính để phát triển các tệp sh, perl, awk, v.v. mà nó tìm thấy là $ 11,029. và điều đó không bao gồm các lớp lót không bao giờ biến nó thành tệp tập lệnh.
cas

11
Dự toán chi phí dựa trên các dòng mã? Điều gì về tất cả những người làm việc để tái yếu tố spaghetti thành một cái gì đó có thể duy trì?
Ngừng làm hại Monica

@OrangeDog bạn luôn có thể cố gắng tính toán điều đó trong chi phí; xem tài liệu để được giải thích về tính toán (với dữ liệu lương rất cũ) và các thông số bạn có thể điều chỉnh.
Stephen Kitt

5
cloccũng tốt: github.com/AlDanial/cloc
SnakeDoc

@StephenKitt> vẫn vậy, vấn đề chính là nó đang đếm ngược. Khi làm sạch mã, bạn thường kết thúc với ít dòng hơn. Chắc chắn rằng bạn có thể cố gắng rửa tay trên đầu để phát sinh phần còn lại của mã để giải thích cho mã bị xóa, nhưng tôi không thấy nó tốt hơn thế nào so với việc chỉ đoán toàn bộ giá ở nơi đầu tiên.
quang phổ

10

wclệnh có thể nhận nhiều đối số, bạn chỉ có thể chuyển tất cả tên tệp sang wcsử dụng +đối số -exechành động của GNU find:

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

Cách khác, trong bash, sử dụng tùy chọn shell globstarđể duyệt qua các thư mục theo cách đệ quy:

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

Các shell khác đi qua đệ quy theo mặc định (ví dụ zsh) hoặc có tùy chọn tương tự như globstar, ít nhất là hầu hết các shell .


1
+1 vì không cần cài đặt phần mềm không chuẩn trên máy mà tôi không có quyền root
Bamboomy

5

Bạn có thể sử dụng findcùng với xargswc:

find . -type f -name '*.h' -o -name '*.c' | xargs wc -l

2
(giả sử đường dẫn tệp không chứa khoảng trắng, dòng mới, trích dẫn đơn, trích dẫn kép của ký tự dấu gạch chéo ngược. Nó cũng có thể xuất ra một số totaldòng nếu một vài wcs đang được gọi.)
Stéphane Chazelas

Có lẽ một số wcvấn đề lệnh có thể được giải quyết bằng cách dẫn findđến while read FILENAME; do . . .donecấu trúc. Và bên trong vòng lặp while sử dụng wc -l. Phần còn lại là tổng hợp các dòng thành một biến và hiển thị nó.
Sergiy Kolodyazhnyy

5

Nếu bạn đang ở trong một môi trường mà bạn không có quyền truy cập, clocv.v.

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

Chạy qua: findtìm kiếm đệ quy cho tất cả các tệp thông thường có tên kết thúc bằng .choặc .hchạy cattrên chúng. Đầu ra được dẫn qua grepđể đếm tất cả các dòng không trống (những dòng có ít nhất một ký tự không khoảng cách).


4

Như đã chỉ ra trong các ý kiến, cat file | wc -lkhông tương đương với wc -l filevì các bản in cũ chỉ có một số trong khi các bản in sau một số lượng và tên tập tin. Tương tự như vậy cat * | wc -lsẽ chỉ in một số, trong khi đó wc -l *sẽ in một dòng thông tin cho mỗi tệp.

Theo tinh thần đơn giản, hãy xem lại câu hỏi thực sự đã hỏi:

Nếu tôi muốn đếm các dòng mã, điều tầm thường là

cat *.c *.h | wc -l

Nhưng nếu tôi có một vài thư mục con thì sao?

Đầu tiên, bạn có thể đơn giản hóa ngay cả lệnh tầm thường của mình thành:

cat *.[ch] | wc -l

Và cuối cùng, tương đương nhiều thư mục con là:

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

Điều này có lẽ có thể được cải thiện theo nhiều cách, chẳng hạn như chỉ giới hạn các tệp phù hợp với các tệp thông thường (không phải thư mục) bằng cách thêm -type fcácbbbut, findlệnh đã cho là tương đương đệ quy chính xáccat *.[ch] .


3

Mẫu sử dụng awk:

find . -name '*.[ch]' -exec wc -l {} \; |
  awk '{SUM+=$1}; END { print "Total number of lines: " SUM }'

Sử dụng +thay thế \;.
Jonathan Leffler

@JonathanLeffler Tại sao?
Hastur

1
@Hastur: Nó chạy wc -lcho các nhóm tác phẩm, chứ không phải như xargshiện, nhưng nó xử lý nhân vật lẻ bóng (như dấu cách) trong tên tập tin mà không cần một trong hai xargshoặc (phi tiêu chuẩn) -print0-0tùy chọn để findxargstương ứng. Đó là một tối ưu hóa nhỏ. Nhược điểm là mỗi lần gọi wcsẽ tạo ra tổng số dòng ở cuối khi được cung cấp nhiều tệp - awktập lệnh sẽ xử lý vấn đề đó. Vì vậy, nó không phải là một slam-dunk, nhưng rất thường xuyên, sử dụng +ở vị trí của \;với findlà một ý tưởng tốt.
Jonathan Leffler

@JonathanLeffler Cảm ơn bạn. Tôi đồng ý. Tuy nhiên, mối quan tâm của tôi là về độ dài của chuỗi tham số được truyền tới wc. Nếu không biết một tiên nghiệm số lượng tệp sẽ được tìm thấy , có nguy cơ vượt qua giới hạn đó hay bằng cách nào đó nó được xử lý bằng cách tìm?
Hastur

2
@Hastur: findnhóm các tệp thành các gói kích thước thuận tiện, không vượt quá giới hạn độ dài cho danh sách đối số trên nền tảng, cho phép môi trường (xuất phát từ độ dài danh sách đối số - vì vậy độ dài của danh sách đối số cộng với chiều dài của môi trường phải nhỏ hơn một giá trị tối đa). IOW, findlàm công việc đúng, như xargscông việc đúng.
Jonathan Leffler

1

lệnh dễ dàng:

find . -name '*.[ch]' | xargs wc -l

(giả sử đường dẫn tệp không chứa khoảng trắng, dòng mới, trích dẫn đơn, trích dẫn kép của ký tự dấu gạch chéo ngược. Nó cũng có thể xuất ra một số totaldòng nếu một vài wcs đang được gọi.)
Stéphane Chazelas

0

Nếu bạn đang dùng Linux, tôi khuyên dùng công cụ của riêng tôi, polyglot . Nó nhanh hơn đáng kể clocvà nhiều tính năng hơn sloccount.

Bạn cũng có thể xây dựng trên BSD, mặc dù không có bất kỳ nhị phân nào được cung cấp.

Bạn có thể gọi nó với

poly .

-2

find . -name \*.[ch] -print | xargs -n 1 wc -lnên làm thủ thuật. Có một số biến thể có thể là tốt, chẳng hạn như sử dụng -execthay vì đường ống đầu ra wc.


4
Nhưng find . -name \*.[ch] -printkhông in nội dung của các tệp, chỉ có tên tệp. Vì vậy, tôi đếm số lượng tập tin thay vì tôi không? Tôi có cần 'xargs' không?
Niklas Rosencrantz

@ Lập trình viên 400 có, bạn cần xargs, và bạn cũng cần xem nhiều wclời mời nếu bạn có nhiều tệp; bạn cần tìm tất cả các totaldòng và tính tổng chúng.
Stephen Kitt

Nếu bạn chỉ muốn tổng số dòng, bạn cần phải làmfind . -name \*.[ch] -print0 | xargs -0 cat | wc -l
fluffy

Lưu ý rằng điều này ( find . -name \*.[ch] -print | wc -l) đếm số lượng tệp (trừ khi tên tệp chứa dòng mới - nhưng điều đó rất bất thường) - nó không tính số lượng dòng trong tệp.
Jonathan Leffler
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.