Cách tốt nhất để đếm số lượng tệp trong một thư mục là gì?


11

Nếu phân tích cú pháp đầu ra lslà nguy hiểm vì nó có thể phá vỡ một số ký tự vui nhộn (dấu cách \n, ...), cách tốt nhất để biết số lượng tệp trong một thư mục là gì?

Tôi thường dựa vào findđể tránh phân tích cú pháp này, nhưng tương tự, find mydir | wc -lsẽ phá vỡ vì những lý do tương tự.

Tôi đang làm việc trên Solaris ngay bây giờ, nhưng tôi đang tìm kiếm một câu trả lời là có thể di chuyển qua các đơn vị khác nhau và các vỏ khác nhau càng tốt.


3
Tôi không chắc đó là bản sao, tôi có thiếu thứ gì không?
rahmu

1
Đây có thể là một bản sao, nhưng không phải là câu hỏi được chỉ ra. findsẽ giúp bạn nhận được số lượng tệp đệ quy (sử dụng -maxdepth 1nếu bạn không muốn điều đó. find mydir -maxdepth 1 -type f -printf \\n | wc -lnên xử lý các ký tự đặc biệt trong tên tệp, vì chúng không bao giờ được in ở vị trí đầu tiên.
Anthon

Câu trả lời:


15

Làm thế nào về thủ thuật này?

find . -maxdepth 1 -exec echo \; | wc -l

Như di động như findwc.


5
Điều này không hoạt động (nó hiển thị n+1các tệp trên hệ thống Debian của tôi). Nó cũng không lọc các tập tin thông thường.
Chris Xuống

4
Tôi chỉ đưa ra một ví dụ chung chung. Nó hoạt động, nhưng cách nó hoạt động phụ thuộc vào cách bạn điều chỉnh findlệnh theo nhu cầu cụ thể của bạn. Có, thư mục này bao gồm tất cả các thư mục, bao gồm .(có thể là lý do tại sao bạn thấy kết quả là n+1).
rozcietrzewiacz

Tôi thích thủ thuật này, rất thông minh; nhưng tôi ngạc nhiên không có cách đơn giản để làm điều đó!
rahmu

3
@ChrisDown OP không chỉ định lọc cho các tệp thông thường, yêu cầu số lượng tệp trong một thư mục. Để thoát khỏi vấn đề n + 1, hãy sử dụng find . -maxdepth 1 ! -name . -exec echo \; | wc -l; một số phiên bản cũ hơn findkhông có -not.
Arcege

3
Lưu ý rằng đó -maxdepthkhông phải là tiêu chuẩn (một phần mở rộng GNU hiện cũng được hỗ trợ bởi một vài triển khai khác).
Stéphane Chazelas

11

Với bash, không có tiện ích bên ngoài, cũng không có vòng lặp:

shopt -s dotglob
files=(*)
echo ${#files[@]}

Trong ksh, thay thế shopt -s dotglobbằng FIGNORE=.?(.). Trong zsh, thay thế nó bằng setopt glob_dotshoặc loại bỏ shoptcuộc gọi và sử dụng files=(*(D)). (Hoặc chỉ bỏ dòng nếu bạn không muốn bao gồm các tệp chấm.) Có thể, nếu bạn không quan tâm đến các tệp chấm:

set -- *
echo $#

Nếu bạn muốn bao gồm các tập tin dấu chấm:

set -- *
if [ -e "$1" ]; then c=$#; else c=0; fi
set .[!.]*
if [ -e "$1" ]; then c=$((c+$#)); fi
set ..?*
if [ -e "$1" ]; then c=$((c+$#)); fi
echo $c

2
Ví dụ đầu tiên in 1cho một thư mục trống khi nullglobkhông được bật. Trong zsh, a=(*(DN));echo ${#a}với vòng loại N( nullglob) không dẫn đến lỗi cho một thư mục trống.
nisetama

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

Nên khá di động cho các hệ thống sau thập niên 80.

Điều đó đếm tất cả các mục thư mục ngoại trừ ...trong thư mục hiện tại.

Để đếm tập tin trong thư mục con là tốt:

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

(cái đó nên có thể mang theo ngay cả với Unix V6 (1975), vì nó không cần -prune)


Một trong những câu trả lời di động hiếm hoi trên trang này, nếu không phải là câu trả lời duy nhất.
xhienne

Tôi đã nâng cấp câu trả lời này ngày hôm qua vì tôi thấy nó cũng hoạt động tốt cho các thư mục khác với thư mục hiện tại ( find dirname ! -name dirname -prune -print). Kể từ đó tôi đã tự hỏi nếu có bất kỳ lý do cụ thể để sử dụng grep -c /thay vì wc -l(có lẽ thường được sử dụng để đếm).
Anthony Geoghegan

1
find dirname ! -name dirnamekhông hoạt động nếu có các thư mục khác trong đó được đặt tên dirname. Nó tốt hơn để sử dụng find dirname/. ! -name .. wc -lđếm số lượng dòng, tên tệp có thể được tạo thành nhiều dòng vì ký tự dòng mới có giá trị như bất kỳ tên nào trong tên tệp.
Stéphane Chazelas

6

Thử:

ls -b1A | wc -l

Các -bsẽ có các ký tự không in được, -Asẽ hiển thị tất cả các file trừ ...và mỗi dòng (mặc định trên một đường ống, nhưng tốt đến mức khó rõ ràng).

Miễn là chúng tôi bao gồm các ngôn ngữ kịch bản cấp cao hơn, đây là một lớp lót trong Python:

python -c 'import os; print len(os.listdir(os.sep))'

Hoặc với đầy đủ 'tìm':

python -c 'import os; print len([j for i in os.walk(os.sep) for j in i[1]+i[2]])'

1

Yoc có thể sử dụng xây dựng như vậy:

I=0; for i in * ; do ((I++)); done ; echo $I

Nhưng tôi e rằng, bạn có thể gặp lỗi như Argument list too long.trong trường hợp bạn có quá nhiều tệp trong thư mục. Tuy nhiên tôi đã thử nghiệm nó trên thư mục với 10 tỷ tệp và nó hoạt động tốt.


3
Chúng sẽ không hoạt động đối với các tệp ẩn trừ khi trình bao được cấu hình để mở rộng các tệp có *.
Lekensteyn

gnu find . -maxdepth 1 -type f | wc -l
Nikhil Mulley

4
@Rush: lệnh này không bao giờ nên tăng "danh sách arg quá dài". Điều đó chỉ xảy ra với lệnh bên ngoài (vì vậy không bao giờ với for.
enzotib

1

Bạn đã xem xét perl, mà nên tương đối di động?

Cái gì đó như:

use File::Find;

$counter = 0;

sub wanted { 
  -f && ++$counter
}

find(\&wanted, @directories_to_search);
print "$counter\n";

0

Hãy thử điều này => Sử dụng ls với -i (cho số nút) & -F (nối thêm tên thư mục với tùy chọn '/').

ls -ilF | egrep -v '/' | wc -l

0

Với một perllớp lót (được định dạng lại để dễ đọc):

perl -e 'opendir($dh, ".");
         while ( readdir($dh) ) {$count++};
         closedir $dh;
         print "$count\n";'

hoặc là

perl -e 'opendir($dh, ".");
         @files = readdir($dh);
         closedir $dh;
         print $#files+1,"\n";'

Bạn có thể sử dụng các perlchức năng sửa đổi các mảng như grephoặc mapvới phiên bản thứ hai. Xem perldoc -f readdirví dụ bằng cách sử dụng grep.


0

Phiên bản đơn giản nhất tôi sử dụng mọi lúc và không bao giờ gặp sự cố là: ls -b1 | wc -l


Bạn có thể gặp vấn đề nếu tên tệp chứa một \nhoặc các ký tự vui nhộn khác (vâng, một số thông báo nhất định cho phép điều này).
rahmu

1
Tôi đã thử điều này một cách rõ ràng trước khi đăng câu trả lời của mình và không có vấn đề gì với nó. Tôi đã sử dụng trình quản lý tệp nautilus để đổi tên tệp để chứa \ n để thử điều này.
Peter

Bạn đúng nó không hoạt động như vậy. Tôi không biết những gì tôi đã làm khi tôi thử nghiệm điều này đầu tiên. Đã thử lại và cập nhật câu trả lời của tôi.
Peter

Không, lệnh vẫn ổn, nhưng đã có một giải pháp tương tự và các tệp ẩn không được tính.
xhienne

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.