Làm cách nào tôi có thể đếm các tệp có phần mở rộng cụ thể và các thư mục chúng nằm trong?


14

Tôi muốn biết có bao nhiêu tệp thông thường có phần mở rộng .ctrong một cấu trúc thư mục phức tạp lớn và cũng có bao nhiêu thư mục mà các tệp này được trải rộng. Đầu ra tôi muốn chỉ là hai số đó.

Tôi đã thấy câu hỏi này về cách lấy số lượng tệp, nhưng tôi cần biết số lượng thư mục của các tệp.

  • Tên tệp của tôi (bao gồm các thư mục) có thể có bất kỳ ký tự nào; họ có thể bắt đầu bằng .hoặc -có không gian hoặc dòng mới.
  • Tôi có thể có một số liên kết tượng trưng có tên kết thúc .cvà liên kết tượng trưng đến thư mục. Tôi không muốn các liên kết tượng trưng được theo dõi hoặc đếm, hoặc ít nhất tôi muốn biết nếu chúng được tính khi nào và khi nào chúng được tính.
  • Cấu trúc thư mục có nhiều cấp độ và thư mục cấp cao nhất (thư mục làm việc) có ít nhất một .ctệp trong đó.

Tôi vội vàng viết một số lệnh trong shell (Bash) để tự đếm chúng, nhưng tôi không nghĩ kết quả này là chính xác ...

shopt -s dotglob
shopt -s globstar
mkdir out
for d in **/; do
     find "$d" -maxdepth 1 -type f -name "*.c" >> out/$(basename "$d")
done
ls -1Aq out | wc -l
cat out/* | wc -l

Điều này đưa ra các khiếu nại về chuyển hướng mơ hồ, bỏ lỡ các tệp trong thư mục hiện tại và gặp các ký tự đặc biệt (ví dụ: đầu ra được chuyển hướng findin các dòng mới trong tên tệp ) và ghi cả đống tệp trống (rất tiếc).

Làm thế nào tôi có thể liệt kê đáng tin cậy các .ctập tin của tôi và các thư mục chứa chúng?


Trong trường hợp có ích, đây là một số lệnh để tạo cấu trúc thử nghiệm với tên xấu và liên kết tượng trưng:

mkdir -p cfiles/{1..3}/{a..b} && cd cfiles
mkdir space\ d
touch -- i.c -.c bad\ .c 'terrible
.c' not-c .hidden.c
for d in space\ d 1 2 2/{a..b} 3/b; do cp -t "$d" -- *.c; done
ln -s 2 dirlink
ln -s 3/b/i.c filelink.c

Trong cấu trúc kết quả, 7 thư mục chứa .ccác tệp và 29 tệp thông thường kết thúc bằng .c(nếu dotglobtắt khi các lệnh được chạy) (nếu tôi bị sai, xin vui lòng cho tôi biết). Đây là những con số tôi muốn.

Xin vui lòng không sử dụng thử nghiệm đặc biệt này.

NB: Câu trả lời trong bất kỳ shell hoặc ngôn ngữ khác sẽ được kiểm tra và đánh giá cao bởi tôi. Nếu tôi phải cài đặt gói mới, không có vấn đề. Nếu bạn biết một giải pháp GUI, tôi khuyến khích bạn chia sẻ (nhưng tôi có thể không đi xa đến mức cài đặt toàn bộ DE để kiểm tra nó) :) Tôi sử dụng Ubuntu MATE 17.10.


Viết một chương trình để đối phó với thói quen lập trình xấu hóa ra khá khó khăn;)
WinEunuuchs2Unix

Câu trả lời:


16

Tôi đã không kiểm tra đầu ra với các liên kết tượng trưng nhưng:

find . -type f -iname '*.c' -printf '%h\0' |
  sort -z |
  uniq -zc |
  sed -zr 's/([0-9]) .*/\1 1/' |
  tr '\0' '\n' |
  awk '{f += $1; d += $2} END {print f, d}'
  • Các findlệnh in tên thư mục của mỗi .ctập tin mà nó tìm thấy.
  • sort | uniq -csẽ cung cấp cho chúng tôi có bao nhiêu tệp trong mỗi thư mục ( sortcó thể không cần thiết ở đây, không chắc chắn)
  • với sed, tôi thay thế tên thư mục bằng 1, do đó loại bỏ tất cả các ký tự lạ có thể, chỉ 1còn lại số lượng và số còn lại
  • cho phép tôi chuyển đổi sang đầu ra được phân tách bằng dòng mới với tr
  • mà sau đó tôi tổng hợp với awk, để có được tổng số tệp và số lượng thư mục chứa các tệp đó. Lưu ý rằng dở đây về cơ bản là giống như NR. Tôi có thể đã bỏ qua việc chèn 1vào sedlệnh và chỉ được in NRở đây, nhưng tôi nghĩ rằng điều này rõ ràng hơn một chút.

Cho đến khi tr, dữ liệu được phân định bằng NUL, an toàn đối với tất cả các tên tệp hợp lệ.


Với zsh và bash, bạn có thể sử dụng printf %qđể có được một chuỗi trích dẫn, chuỗi này sẽ không có dòng mới trong đó. Vì vậy, bạn có thể làm một cái gì đó như:

shopt -s globstar dotglob nocaseglob
printf "%q\n" **/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'

Tuy nhiên, mặc dù **không được phép mở rộng cho các liên kết tượng trưng đến các thư mục , tôi không thể có được đầu ra mong muốn trên bash 4.4.18 (1) (Ubuntu 16.04).

$ shopt -s globstar dotglob nocaseglob
$ printf "%q\n" ./**/*.c | awk -F/ '{NF--; f++} !c[$0]++{d++} END {print f, d}'
34 15
$ echo $BASH_VERSION
4.4.18(1)-release

Nhưng zsh hoạt động tốt và lệnh có thể được đơn giản hóa:

$ printf "%q\n" ./**/*.c(D.:h) | awk '!c[$0]++ {d++} END {print NR, d}'
29 7

Dcho phép toàn cầu này chọn các tệp chấm, .chọn các tệp thông thường (vì vậy, không phải là liên kết tượng trưng) và :hchỉ in đường dẫn thư mục chứ không phải tên tệp (như find's %h) (Xem các phần về Tạosửa đổi tên tệp ). Vì vậy, với lệnh awk, chúng ta chỉ cần đếm số lượng thư mục duy nhất xuất hiện và số dòng là số tập tin.


Thật tuyệt vời. Sử dụng chính xác những gì cần thiết và không còn nữa. Cảm ơn bạn đã giảng dạy :)
Zanna

@Zanna nếu bạn đăng một số lệnh để tạo lại cấu trúc thư mục với các liên kết tượng trưng và đầu ra dự kiến ​​với các liên kết tượng trưng, ​​tôi có thể khắc phục điều này cho phù hợp.
muru

Tôi đã thêm một số lệnh để tạo cấu trúc kiểm tra (không cần phức tạp như bình thường) với các liên kết tượng trưng.
Zanna

@Zanna Tôi nghĩ rằng lệnh này không cần bất kỳ điều chỉnh nào để có được 29 7. Nếu tôi thêm -Lvào find, điều đó đi lên 41 10. Bạn cần đầu ra nào?
muru

1
Đã thêm một phương thức zsh + awk. Có lẽ có một số cách để tự zsh in số đếm cho tôi, nhưng không biết làm thế nào.
muru

11

Python có os.walk, giúp cho các tác vụ như thế này trở nên dễ dàng, trực quan và tự động mạnh mẽ ngay cả khi đối mặt với các tên tệp lạ như các tên chứa các ký tự dòng mới. Tập lệnh Python 3 này, mà tôi đã đăng ban đầu trong trò chuyện , dự định sẽ được chạy trong thư mục hiện tại (nhưng không phải nằm trong thư mục hiện tại và bạn có thể thay đổi đường dẫn mà nó đi qua os.walk):

#!/usr/bin/env python3

import os

dc = fc = 0
for _, _, fs in os.walk('.'):
    c = sum(f.endswith('.c') for f in fs)
    if c:
        dc += 1
        fc += c
print(dc, fc)

Điều đó in số lượng thư mục chứa trực tiếp ít nhất một tệp có tên kết thúc .c, theo sau là khoảng trắng, theo sau là số lượng tệp có tên kết thúc .c. Các tệp "Ẩn" - nghĩa là các tệp có tên bắt đầu bằng .- được bao gồm và các thư mục ẩn tương tự nhau.

os.walkđệ quy đi qua một hệ thống phân cấp thư mục. Nó liệt kê tất cả các thư mục có thể truy cập đệ quy từ điểm bắt đầu mà bạn cung cấp, mang lại thông tin về mỗi thư mục dưới dạng một bộ ba giá trị , root, dirs, files. Đối với mỗi thư mục, nó đi qua (bao gồm cả thư mục đầu tiên có tên bạn đặt cho nó):

  • rootgiữ tên đường dẫn của thư mục đó. Lưu ý rằng điều này hoàn toàn không liên quan đến "thư mục gốc" của hệ thống /(và cũng không liên quan đến /root) mặc dù nó sẽ đi đến những thứ đó nếu bạn bắt đầu ở đó. Trong trường hợp này, rootbắt đầu tại đường dẫn .--ie, thư mục hiện tại - và đi khắp mọi nơi bên dưới nó.
  • dirsgiữ một danh sách các tên đường dẫn của tất cả các thư mục con của thư mục có tên hiện đang được giữ root.
  • filesgiữ một danh sách các tên đường dẫn của tất cả các tệp nằm trong thư mục có tên hiện đang được giữ rootnhưng đó không phải là thư mục. Lưu ý rằng điều này bao gồm các loại tệp khác ngoài các tệp thông thường, bao gồm các liên kết tượng trưng, ​​nhưng có vẻ như bạn không mong đợi bất kỳ mục nào như vậy kết thúc .cvà quan tâm đến việc xem bất kỳ mục nào.

Trong trường hợp này, tôi chỉ cần kiểm tra phần tử thứ ba của bộ dữ liệu files(mà tôi gọi fstrong tập lệnh). Giống như findlệnh, Python os.walkchuyển qua các thư mục con đối với tôi; điều duy nhất tôi phải tự kiểm tra là tên của các tệp mà mỗi tệp chứa. findTuy nhiên, không giống như lệnh, os.walktự động cung cấp cho tôi một danh sách các tên tệp đó.

Kịch bản đó không theo các liên kết tượng trưng. Bạn rất có thể không muốn các liên kết tượng được theo dõi cho một hoạt động như vậy, bởi vì chúng có thể tạo thành các chu kỳ và bởi vì ngay cả khi không có chu kỳ, các tệp và thư mục tương tự có thể được duyệt và đếm nhiều lần nếu chúng có thể truy cập thông qua các liên kết tượng trưng khác nhau.

Nếu bạn đã từng muốn os.walktheo liên kết tượng trưng - điều mà bạn thường không muốn - thì bạn có thể chuyển qua followlinks=truenó. Đó là, thay vì viết os.walk('.')bạn có thể viết os.walk('.', followlinks=true). Tôi nhắc lại rằng bạn hiếm khi muốn điều đó, đặc biệt là đối với một tác vụ như thế này khi bạn liệt kê đệ quy toàn bộ cấu trúc thư mục, bất kể nó lớn đến đâu và đếm tất cả các tệp trong đó đáp ứng một số yêu cầu.


7

Tìm + Perl:

$ find . -type f -iname '*.c' -printf '%h\0' | 
    perl -0 -ne '$k{$_}++; }{ print scalar keys %k, " $.\n" '
7 29

Giải trình

Các findlệnh sẽ tìm thấy bất kỳ tập tin thường xuyên (vì vậy không liên kết tượng trưng hoặc thư mục) và sau đó in tên của thư mục họ đang ở trong ( %h) tiếp theo \0.

  • perl -0 -ne: đọc dòng đầu vào theo dòng ( -n) và áp dụng tập lệnh được cung cấp -echo từng dòng. Các -0bộ tách dòng đầu vào \0vì vậy chúng tôi có thể đọc đầu vào vô-phân.
  • $k{$_}++: $_là một biến đặc biệt lấy giá trị của dòng hiện tại. Điều này được sử dụng như là một khóa cho hàm băm %k , có giá trị là số lần mỗi dòng đầu vào (tên thư mục) được nhìn thấy.
  • }{: đây là một cách viết tốc ký END{}. Bất kỳ lệnh nào sau đó }{sẽ được thực hiện một lần, sau khi tất cả đầu vào đã được xử lý.
  • print scalar keys %k, " $.\n": keys %ktrả về một mảng các khóa trong hàm băm %k. scalar keys %kđưa ra số lượng phần tử trong mảng đó, số lượng thư mục được nhìn thấy. Điều này được in cùng với giá trị hiện tại của $., một biến đặc biệt chứa số dòng đầu vào hiện tại. Vì điều này được chạy ở cuối, số dòng đầu vào hiện tại sẽ là số của dòng cuối cùng, vì vậy số lượng dòng được nhìn thấy cho đến nay.

Bạn có thể mở rộng lệnh perl sang điều này, cho rõ ràng:

find  . -type f -iname '*.c' -printf '%h\0' | 
    perl -0 -e 'while($line = <STDIN>){
                    $dirs{$line}++; 
                    $tot++;
                } 
                $count = scalar keys %dirs; 
                print "$count $tot\n" '

4

Đây là gợi ý của tôi:

#!/bin/bash
tempfile=$(mktemp)
find -type f -name "*.c" -prune >$tempfile
grep -c / $tempfile
sed 's_[^/]*$__' $tempfile | sort -u | grep -c /

Kịch bản ngắn này tạo ra một tempfile, tìm mọi tệp trong và dưới thư mục hiện tại kết thúc bằng .cvà ghi danh sách vào tempfile. grepsau đó được sử dụng để đếm các tệp (sau đây Làm thế nào tôi có thể nhận được số lượng tệp trong thư mục bằng cách sử dụng dòng lệnh? ) hai lần: Lần thứ hai, các thư mục được liệt kê nhiều lần sẽ bị xóa bằng cách sử dụng sort -utên tệp từ mỗi dòng bằng cách sử dụng sed.

Điều này cũng hoạt động đúng với các dòng mới trong tên tệp: grep -c /chỉ đếm các dòng có dấu gạch chéo và do đó chỉ xem xét dòng đầu tiên của tên tệp nhiều dòng trong danh sách.

Đầu ra

$ tree
.
├── 1
   ├── 1
      ├── test2.c
      └── test.c
   └── 2
       └── test.c
└── 2
    ├── 1
       └── test.c
    └── 2

$ tempfile=$(mktemp);find -type f -name "*.c" -prune >$tempfile;grep -c / $tempfile;sed 's_[^/]*$__' $tempfile | sort -u | grep -c /
4
3

4

Vỏ nhỏ

Tôi đề xuất một shell bash nhỏ với hai dòng lệnh chính (và một biến filetypeđể giúp dễ dàng chuyển đổi để tìm kiếm các loại tệp khác).

Nó không tìm kiếm hoặc trong các liên kết tượng trưng, ​​chỉ các tệp thông thường.

#!/bin/bash

filetype=c
#filetype=pdf

# count the 'filetype' files

find -type f -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l | tr '\n' ' '

# count directories containing 'filetype' files

find -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)'" \;|grep 'contains file(s)$'|wc -l

Vỏ sò dài

Đây là một phiên bản dài dòng hơn cũng xem xét các liên kết tượng trưng,

#!/bin/bash

filetype=c
#filetype=pdf

# counting the 'filetype' files

echo -n "number of $filetype files in the current directory tree: "
find -type f -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l

echo -n "number of $filetype symbolic links in the current directory tree: "
find -type l -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l
echo -n "number of $filetype normal files in the current directory tree: "
find -type f -name "*.$filetype" -ls|sed 's#.* \./##'|wc -l
echo -n "number of $filetype symbolic links in the current directory tree including linked directories: "
find -L -type f -name "*.$filetype" -ls 2> /tmp/c-counter |sed 's#.* \./##' | wc -l; cat /tmp/c-counter; rm /tmp/c-counter

# list directories with and without 'filetype' files (good for manual checking; comment away after test)
echo '---------- list directories:'
 find    -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)' || echo '{} empty'" \;
echo ''
#find -L -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)' || echo '{} empty'" \;

# count directories containing 'filetype' files

echo -n "number of directories with $filetype files: "
find -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)'" \;|grep 'contains file(s)$'|wc -l

# list and count directories including symbolic links, containing 'filetype' files
echo '---------- list all directories including symbolic links:'
find -L -type d -exec bash -c "ls -AF '{}' |grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)' || echo '{} empty'" \;
echo ''
echo -n "number of directories (including symbolic links) with $filetype files: "
find -L -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null && echo '{} contains file(s)'" \; 2>/dev/null |grep 'contains file(s)$'|wc -l

# count directories without 'filetype' files (good for checking; comment away after test)

echo -n "number of directories without $filetype files: "
find -type d -exec bash -c "ls -AF '{}'|grep -e '\.'${filetype}$ -e '\.'${filetype}'\*'$ > /dev/null || echo '{} empty'" \;|grep 'empty$'|wc -l

Đầu ra thử nghiệm

Từ bản tóm tắt ngắn:

$ ./ccntr 
29 7

Từ bản tóm tắt dài dòng:

$ LANG=C ./c-counter
number of c files in the current directory tree: 29
number of c symbolic links in the current directory tree: 1
number of c normal files in the current directory tree: 29
number of c symbolic links in the current directory tree including linked directories: 42
find: './cfiles/2/2': Too many levels of symbolic links
find: './cfiles/dirlink/2': Too many levels of symbolic links
---------- list directories:
. empty
./cfiles contains file(s)
./cfiles/2 contains file(s)
./cfiles/2/b contains file(s)
./cfiles/2/a contains file(s)
./cfiles/3 empty
./cfiles/3/b contains file(s)
./cfiles/3/a empty
./cfiles/1 contains file(s)
./cfiles/1/b empty
./cfiles/1/a empty
./cfiles/space d contains file(s)

number of directories with c files: 7
---------- list all directories including symbolic links:
. empty
./cfiles contains file(s)
./cfiles/2 contains file(s)
find: './cfiles/2/2': Too many levels of symbolic links
./cfiles/2/b contains file(s)
./cfiles/2/a contains file(s)
./cfiles/3 empty
./cfiles/3/b contains file(s)
./cfiles/3/a empty
./cfiles/dirlink empty
find: './cfiles/dirlink/2': Too many levels of symbolic links
./cfiles/dirlink/b contains file(s)
./cfiles/dirlink/a contains file(s)
./cfiles/1 contains file(s)
./cfiles/1/b empty
./cfiles/1/a empty
./cfiles/space d contains file(s)

number of directories (including symbolic links) with c files: 9
number of directories without c files: 5
$ 

4

Đơn giản Perl một lót:

perl -MFile::Find=find -le'find(sub{/\.c\z/ and -f and $c{$File::Find::dir}=++$c}, @ARGV); print 0 + keys %c, " $c"' dir1 dir2

Hoặc đơn giản hơn với findlệnh:

find dir1 dir2 -type f -name '*.c' -printf '%h\0' | perl -l -0ne'$c{$_}=1}{print 0 + keys %c, " $."'

Nếu bạn thích chơi gôn và gần đây (như chưa đầy thập kỷ) Perl:

perl -MFile::Find=find -E'find(sub{/\.c$/&&-f&&($c{$File::Find::dir}=++$c)},".");say 0+keys%c," $c"'
find -type f -name '*.c' -printf '%h\0'|perl -0nE'$c{$_}=1}{say 0+keys%c," $."'

2

Xem xét sử dụng locatelệnh nhanh hơn nhiều so với findlệnh.

Chạy trên dữ liệu thử nghiệm

$ sudo updatedb # necessary if files in focus were added `cron` daily.
$ printf "Number Files: " && locate -0r "$PWD.*\.c$" | xargs -0 -I{} sh -c 'test ! -L "$1" && echo "regular file"' _  {} | wc -l &&  printf "Number Dirs.: " && locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -cu | wc -l
Number Files: 29
Number Dirs.: 7

Cảm ơn Muru vì câu trả lời của anh ấy đã giúp tôi vượt qua các liên kết tượng trưng trong số lượng tập tin trong câu trả lời của Unix & Linux .

Cảm ơn Terdon vì câu trả lời của anh ấy $PWD(không hướng vào tôi) trong câu trả lời của Unix & Linux .


Câu trả lời gốc dưới đây được tham khảo bởi ý kiến

Hình thức ngắn:

$ cd /
$ sudo updatedb
$ printf "Number Files: " && locate -cr "$PWD.*\.c$"
Number Files: 3523
$ printf "Number Dirs.: " && locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l 
Number Dirs.: 648
  • sudo updatedbCập nhật cơ sở dữ liệu được sử dụng bởi locatelệnh nếu .ccác tệp được tạo hôm nay hoặc nếu bạn đã xóa .ccác tệp ngày hôm nay.
  • locate -cr "$PWD.*\.c$"định vị tất cả .ccác tệp trong thư mục hiện tại và đó là con ( $PWD). Thay vì in tên tệp và in số lượng với -cđối số. Các rquy định cụ thể regex thay vì mặc định *pattern*phù hợp mà có thể mang lại quá nhiều kết quả.
  • locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l. Xác định vị trí tất cả *.ccác tập tin trong thư mục hiện tại và dưới đây. Xóa tên tệp sedchỉ để lại tên thư mục. Đếm số lượng tệp trong mỗi thư mục bằng cách sử dụng uniq -c. Đếm số lượng thư mục với wc -l.

Bắt đầu tại thư mục hiện tại với một lớp lót

$ cd /usr/src
$ printf "Number Files: " && locate -cr "$PWD.*\.c$" &&  printf "Number Dirs.: " && locate -r "$PWD.*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l
Number Files: 3430
Number Dirs.: 624

Lưu ý cách đếm tập tin và số lượng thư mục đã thay đổi. Tôi tin rằng tất cả người dùng có /usr/srcthư mục và có thể chạy các lệnh trên với số lượng khác nhau tùy thuộc vào số lượng hạt nhân được cài đặt.

Mẫu dài:

Các dạng dài bao gồm thời gian, do đó bạn có thể thấy cách nhanh hơn nhiều locatelà qua find. Ngay cả khi bạn phải chạy sudo updatedbnó nhanh hơn nhiều lần so với một lần duy nhất find /.

───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ sudo time updatedb
0.58user 1.32system 0:03.94elapsed 48%CPU (0avgtext+0avgdata 7568maxresident)k
48inputs+131920outputs (1major+3562minor)pagefaults 0swaps
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ time (printf "Number Files: " && locate -cr $PWD".*\.c$")
Number Files: 3523

real    0m0.775s
user    0m0.766s
sys     0m0.012s
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ time (printf "Number Dirs.: " && locate -r $PWD".*\.c$" | sed 's%/[^/]*$%/%' | uniq -c | wc -l) 
Number Dirs.: 648

real    0m0.778s
user    0m0.788s
sys     0m0.027s
───────────────────────────────────────────────────────────────────────────────────────────

Lưu ý: Đây là tất cả các tệp trên TẤT CẢ các ổ đĩa và phân vùng. tức là chúng ta cũng có thể tìm kiếm các lệnh Windows:

$ time (printf "Number Files: " && locate *.exe -c)
Number Files: 6541

real    0m0.946s
user    0m0.761s
sys     0m0.060s
───────────────────────────────────────────────────────────────────────────────────────────
rick@alien:~/Downloads$ time (printf "Number Dirs.: " && locate *.exe | sed 's%/[^/]*$%/%' | uniq -c | wc -l) 
Number Dirs.: 3394

real    0m0.942s
user    0m0.803s
sys     0m0.092s

Tôi có ba phân vùng NTFS Windows 10 tự động được gắn vào /etc/fstab. Hãy nhận biết vị trí biết tất cả mọi thứ!

Số lượng thú vị:

$ time (printf "Number Files: " && locate / -c &&  printf "Number Dirs.: " && locate / | sed 's%/[^/]*$%/%' | uniq -c | wc -l)
Number Files: 1637135
Number Dirs.: 286705

real    0m15.460s
user    0m13.471s
sys     0m2.786s

Phải mất 15 giây để đếm 1.637.135 tệp trong thư mục 286.705. YMMV.

Để biết chi tiết về locatexử lý regex của lệnh (dường như không cần thiết trong Hỏi & Đáp này nhưng chỉ được sử dụng trong trường hợp), vui lòng đọc phần này: Sử dụng "định vị" trong một số thư mục cụ thể?

Đọc thêm từ các bài báo gần đây:


1
Điều này không tính các tập tin trong một thư mục cụ thể. Như bạn chỉ ra, nó đếm tất cả các tệp (hoặc thư mục hoặc bất kỳ loại tệp nào khác) khớp .c(lưu ý rằng nó sẽ bị hỏng nếu có một tệp có -.ctrong thư mục hiện tại vì bạn không trích dẫn *.c) và sau đó nó sẽ in tất cả các thư mục trong hệ thống, bất kể chúng có chứa tệp .c hay không.
terdon

@terdon Bạn có thể vượt qua một thư mục ~/my_c_progs/*.c. Đó là đếm 638 thư mục với .ccác chương trình, tổng số thư mục sẽ hiển thị sau 286,705. Tôi sẽ sửa lại câu trả lời để trích dẫn kép `" * .c ". Cảm ơn vì tiền hỗ trợ.
WinEunuuchs2Unix

3
Có, bạn có thể sử dụng một cái gì đó như locate -r "/path/to/dir/.*\.c$", nhưng điều đó không được đề cập ở bất cứ đâu trong câu trả lời của bạn. Bạn chỉ đưa ra một liên kết đến một câu trả lời khác đề cập đến điều này nhưng không có lời giải thích về cách điều chỉnh nó để trả lời câu hỏi đang được hỏi ở đây. Toàn bộ câu trả lời của bạn tập trung vào cách đếm tổng số tệp và thư mục trên hệ thống, không liên quan đến câu hỏi được hỏi là "làm thế nào tôi có thể đếm số lượng tệp .c và số lượng thư mục chứa. c tập tin trong một thư mục cụ thể ". Ngoài ra, số của bạn sai, hãy thử nó trong ví dụ trong OP.
terdon

@terdon Cảm ơn bạn đã đóng góp. Tôi đã cải thiện câu trả lời với các đề xuất của bạn và câu trả lời bạn đã đăng trên trang SE khác cho $PWDbiến: unix.stackexchange.com/a/188191/200094
WinEunuuchs2Unix

1
Bây giờ bạn phải đảm bảo rằng $PWDkhông chứa các ký tự có thể đặc biệt trong regex
muru
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.