Làm cách nào tôi có thể nhận được số lượng tệp trong một thư mục bằng dòng lệnh?


193

Tôi có một thư mục với một số lượng lớn các tập tin. Tôi không thấy một lscông tắc để cung cấp số đếm. Có một số phép thuật dòng lệnh để có được một số lượng các tập tin?



tree . | tailhoặc tree -a . | tailbao gồm các tệp / thư mục ẩn, treeđược đệ quy nếu đó là những gì bạn muốn.
CodyChan

Câu trả lời:


239

Sử dụng một định nghĩa rộng của "tập tin"

ls | wc -l

(lưu ý rằng nó không tính các tệp ẩn và giả sử rằng tên tệp không chứa ký tự dòng mới).

Để bao gồm các tệp ẩn (ngoại trừ ...) và tránh các vấn đề với các ký tự dòng mới, cách chính tắc là:

find . ! -name . -prune -print | grep -c /

Hoặc đệ quy:

find .//. ! -name . -print | grep -c //

23
wclà một chương trình "đếm từ". Việc -lchuyển đổi làm cho nó để đếm dòng. Trong trường hợp này, nó đếm các dòng trong đầu ra từ ls. Đây luôn là cách tôi được dạy để lấy số lượng tập tin cho một thư mục nhất định.
Sandy

20
xin vui lòng thêm lưu ý rằng lskhông ls -1nếu đầu ra là một ống.
lesmana

6
không nhận được mọi thứ trong một thư mục - bạn cũng đã bỏ lỡ các tệp chấm và cũng thu thập thêm một vài dòng. Một thư mục trống sẽ vẫn trả về 1 dòng. Và nếu bạn gọi ls -la, bạn sẽ nhận được ba dòng trong thư mục. Bạn muốn ls -lA | wc -lbỏ qua ...các mục. Tuy nhiên, bạn vẫn sẽ được nghỉ từng người một.

1
Một thư mục trống trả về 0 cho tôi
James Roth

2
Một cách tiếp cận đã được sửa, sẽ không nhân đôi số tệp có dòng mới trong tên, sẽ là: ls -q | wc -l- mặc dù lưu ý rằng các tệp ẩn sẽ vẫn không được tính theo phương pháp này và các thư mục đó sẽ được tính.
Godlygeek 3/03/2015

31

Đối với định nghĩa hẹp của tập tin:

 find . -maxdepth 1 -type f | wc -l

Và tất nhiên bạn có thể bỏ qua việc -maxdepth 1đếm các tệp đệ quy (hoặc điều chỉnh nó cho độ sâu tìm kiếm tối đa mong muốn).
dùng7089

1
Nếu bạn có một tệp có tên chứa một dòng mới, phương pháp này sẽ đếm không chính xác hai lần.
godlygeek

7
Một cách tiếp cận đúng, sẽ không nhân đôi số tập tin với dòng mới trong tên, sẽ là thế này:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek

+1 Cho phép các tập tin ẩn và bỏ qua các thư mục
Michael Durrant

14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: Lưu ý ls - <số một> | wc - <thư-l>


10
Hầu hết các phiên bản lslàm -1tự động khi đầu ra là một đường ống.
Dennis Williamson

3
@Dennis thật thú vị Tôi không biết rằng một ứng dụng có thể cho biết đầu ra của nó sẽ đi vào đường ống.
xenoterracide

1
Tôi đã sửa phiên bản này vì nó rõ ràng hơn. Mặc dù, vâng, tôi sử dụng -1 nếu nó được đặt (thử: ls | cat), tôi thấy cú pháp -1 rõ ràng hơn.
gabe.

3
@xenoterracide: Ở Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson

2
Trong các thử nghiệm của tôi, nó cũng nhanh hơn đáng kể khi cung cấp tùy chọn -f để tránh ls sắp xếp tên tệp. Thật không may, bạn vẫn nhận được câu trả lời sai nếu tên tệp của bạn chứa dòng mới.
Phường Samuel Edwin

10

Có lẽ câu trả lời đầy đủ nhất bằng cách sử dụng ls/ wccặp là

ls -Aq | wc -l

nếu bạn muốn đếm tập tin dấu chấm, và

ls -q | wc -l

nếu không thì.

  • -Alà để đếm các tập tin dấu chấm, nhưng bỏ qua ....
  • -qlàm lsthay thế ký tự không phải đồ thị, nhân vật đặc biệt xuống dòng, với ?, làm cho đầu ra 1 dòng cho mỗi file

Để có được đầu ra một dòng từ lstrong thiết bị đầu cuối (nghĩa là không có đường ống vào wc), -1tùy chọn phải được thêm vào.

(hành vi lsđược thử nghiệm với coreutils 8.23)


2
Như bạn đã nói, -1không cần thiết. Đối với "nó xử lý các dòng mới trong tên tệp một cách hợp lý với đầu ra của bàn điều khiển" , điều này là do công -qtắc (mà bạn nên sử dụng thay -bvì vì nó di động), "Buộc mỗi trường hợp ký tự tên tệp không thể in và ký tự <tab> được viết dưới dạng ký tự <question-mark> ('?'). Việc triển khai có thể cung cấp tùy chọn này theo mặc định nếu đầu ra là cho thiết bị đầu cuối. " Vì vậy, ví dụ: ls -Aq | wc -lđể đếm tất cả các tệp / thư mục hoặc ls -qp | grep -c /chỉ đếm các thư mục không bị ẩn, v.v ...
don_crissti

Cảm ơn vì đầu vào của bạn. Thay đổi -bthành -q.
Frax

7

Nếu bạn biết thư mục hiện tại chứa ít nhất một tệp không bị ẩn:

set -- *; echo "$#"

Điều này rõ ràng là khái quát cho bất kỳ toàn cầu.

Trong một kịch bản, điều này đôi khi có tác dụng phụ đáng tiếc là ghi đè các tham số vị trí. Bạn có thể giải quyết vấn đề đó bằng cách sử dụng một lớp con hoặc với một chức năng (phiên bản Bourne / POSIX) như:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Một giải pháp thay thế là $(ls -d -- * | wc -l). Nếu toàn cầu là *, lệnh có thể được rút ngắn thành $(ls | wc -l). Phân tích cú pháp đầu ra lsluôn khiến tôi khó chịu, nhưng ở đây nó sẽ hoạt động miễn là tên tệp của bạn không chứa dòng mới hoặc bạn lsthoát chúng. Và $(ls -d -- * 2>/dev/null | wc -l)có lợi thế xử lý trường hợp của một quả cầu không khớp một cách duyên dáng (nghĩa là nó trả về 0 trong trường hợp đó, trong khi set *phương thức yêu cầu kiểm tra một cách khéo léo nếu quả cầu có thể trống).

Nếu tên tệp có thể chứa các ký tự dòng mới, một cách khác là sử dụng $(ls -d ./* | grep -c /).

Bất kỳ giải pháp nào dựa vào việc vượt qua việc mở rộng toàn cầu đều lscó thể thất bại với danh sách đối số lỗi quá dài nếu có nhiều tệp phù hợp.


1
Bạn có thực sự muốn tạo 13.923 tham số vị trí? Và bạn nên biến biến cục bộ của bạn localhoặc loại bỏ nó: eval $1=$#hoặc chỉ sử dụng echo $#và làm number_of_files=$(count_words *).
Dennis Williamson

1
@Dennis: một phần của vấn đề là để tránh giả mạo. Tôi đoán đó không phải là một mối quan tâm của thế kỷ 21. Ok, tôi thừa nhận tôi không quan tâm đến các vỏ không phải POSIX nữa, vì vậy tôi có thể tránh được biến tạm thời.
Gilles

Tại sao bạn lại trừ đi một thứ $#(bạn chưa làm điều đó trước khi chỉnh sửa)?
Dennis Williamson

@Dennis: Tôi vẫn đang tránh một ngã ba (tốt, nó sẽ tạo ra sự khác biệt trên các máy có CPU chậm như bộ định tuyến) và chuyển một tên biến như $1. Vì vậy, những gì tôi muốn đếm là số lượng tham số không phải là tham số đầu tiên. (Tôi không thể sử dụng shiftvì tôi cần giữ tên biến xung quanh.) (Umm, bây giờ nếu bạn hỏi về dòng đầu tiên ...)
Gilles

@Dennis: hãy nghĩ về nó, tôi có thể sử dụng shiftnếu tôi đúng lúc.
Gilles

7

Tôi đã tìm thấy du --inodeshữu ích, nhưng tôi không chắc phiên bản nào của dunó yêu cầu. Nó sẽ nhanh hơn đáng kể so với các phương pháp thay thế sử dụng findwc.

Trên Ubuntu 17.10, các công việc sau:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Kết hợp với | sort -nrđể sắp xếp giảm dần theo số lượng nút chứa.


5

Trong khi sử dụng cặp ls / wc nếu chúng ta thêm -U, nó sẽ nhanh hơn nhiều (không sắp xếp).

ls -AqU | wc -l

1
-Ulà đặc thù của GNU mặc dù.
Stéphane Chazelas

4

Sau khi cài đặt lệnh cây, chỉ cần gõ:

tree

Nếu bạn cũng muốn các tập tin ẩn:

tree -a

Nếu bạn đang sử dụng Debian / Mint / Ubuntu Linux, hãy gõ lệnh sau để cài đặt lệnh cây:

sudo apt-get install tree

Tùy chọn -L được sử dụng để chỉ định mức hiển thị tối đa của cây thư mục. Lệnh cây không chỉ đếm số lượng tệp, mà còn cả số lượng thư mục, xem xét bao nhiêu cấp độ của cây thư mục tùy thích.


Khi tôi gõ cây, tôi nhận được một loại đầu ra cây vào màn hình của thư mục tôi đang ở nhưng tôi không thể thấy số lượng tệp được hiển thị.
charlesdarwin

2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1sẽ làm cho nó không đệ quy, findđược đệ quy theo mặc định
  • -type f sẽ chỉ bao gồm các tệp
  • -printf .là một liên lạc dễ thương. nó in một dấu chấm cho mỗi tệp thay vì tên tệp và bây giờ điều này có thể xử lý bất kỳ tên tệp nào và cũng lưu dữ liệu; chúng ta chỉ cần đếm số chấm :)
  • | wc -c đếm nhân vật

1

Không có đường ống, không có bản sao chuỗi, không có ngã ba, chỉ đơn giản là bash một lớp lót

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount

1
Cung cấp giá trị 1 nếu không có tệp trong thư mục. Không đếm tập tin, đếm tập tin và thư mục.
steve

1

Đây là một kỹ thuật khác dọc theo dòng của một Gilles được đăng :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

tạo ra một mảng với 13.923 phần tử (nếu đó là bao nhiêu tệp).


Điểm của cmảng đó là gì? word_count() { echo "$#"; }sẽ là đủ Điểm của giải pháp @Gilles là lưu trữ số đếm trong một biến được trả về để tránh phải sử dụng thay thế lệnh (liên quan đến một ngã ba và đường ống trong các vỏ khác với ksh93).
Stéphane Chazelas

1
find . -type f -maxdepth 1 |  wc -l 

Điều này chỉ có thể liệt kê các tập tin trong thư mục hiện tại.


find . -type fsẽ tìm thấy các tập tin trong thư mục hiện tại, và, theo cách đệ quy, trong các thư mục con.
dhag

0

Hãy thử điều này tôi hy vọng câu trả lời này sẽ giúp bạn

echo $((`ls -l | wc -l` -1 ))


0

Cải thiện một số câu trả lời được đưa ra trước đây nhưng lần này làm rõ ràng.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Thật đáng để chú ý việc sử dụng một số lệnh yêu thích như tailcut. Ngoài ra, lưu ý rằng cây không có sẵn theo mặc định. Lệnh trên nắm bắt thông tin đầu tiên về thư mục ở cấp 1, sau đó lấy dòng cuối cùng tail -n 1có mục tiêu của chúng tôi và kết thúc bằng cutcách lấy từ thứ ba.

Ví dụ: định vị trong /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Sau đó, những gì về số lượng thư mục?



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.