Đếm số tệp trong mỗi thư mục con


21

Tôi muốn một lệnh BASH chỉ liệt kê số lượng tệp trong mỗi thư mục con của một thư mục.

Ví dụ như trong thư mục /tmpcó được dir1, dir2, ... Tôi muốn xem:

`dir1` : x files 
`dir2` : x files ...

Câu trả lời:


32

Giả sử bạn chỉ muốn số lượng tệp đệ quy, không phải thư mục và các loại khác, một cái gì đó như thế này sẽ hoạt động:

find . -maxdepth 1 -mindepth 1 -type d | while read dir; do
  printf "%-25.25s : " "$dir"
  find "$dir" -type f | wc -l
done

Ngoài ra, tôi nhận được "find: warning: bạn đã chỉ định tùy chọn -maxdepth sau một loại đối số không phải tùy chọn -type, nhưng các tùy chọn không theo vị trí (-maxdepth ảnh hưởng đến các thử nghiệm được chỉ định trước nó cũng như các tùy chọn được chỉ định sau nó). trước những tranh luận khác. "
jldupont

2
Cả hai câu trả lời được đưa ra cho đến nay sẽ cho kết quả không chính xác trong trường hợp không chắc là có các tệp có tên bao gồm các ký tự dòng mới. Bạn có thể xử lý việc đó với find... -print0 | xargs -0....
Scott

@jldupont: di chuyển các đối số độ sâu trước loại d trọng, và tôi đã chỉnh sửa câu trả lời.
Thor

Có, và để tôi thêm thông tin rằng giải pháp tuyệt vời này sẽ không lấy bất kỳ biến số bên ngoài nào và do đó sẽ hoạt động với bash alias!!
cú pháp

nhanh chóng và đường ống sort -rn -k 2,2 -t$':'bạn có được danh sách DESC
Andre Figueiredo

14

Nhiệm vụ này mê hoặc tôi đến mức tôi muốn tự mình tìm ra giải pháp. Nó thậm chí không có một vòng lặp while và CÓ THỂ được nhanh hơn về tốc độ thực thi. Không cần phải nói, những nỗ lực của Thor đã giúp tôi rất nhiều để hiểu mọi thứ một cách chi tiết.

Vì vậy, đây là của tôi:

find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "{} : $(find "{}" -type f | wc -l)" file\(s\)' \;

Nó có vẻ khiêm tốn vì một lý do, vì nó mạnh hơn vẻ ngoài của nó. :-)

Tuy nhiên, nếu bạn có ý định đưa cái này vào .bash_aliasestập tin của mình thì nó phải giống như thế này:

alias somealias='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '\''echo "{} : $(find "{}" -type f | wc -l)" file\(s\)'\'' \;'

Lưu ý việc xử lý rất khó khăn của dấu ngoặc đơn lồng nhau . Và không, không thể sử dụng dấu ngoặc kép cho sh -cđối số.


Nó chậm hơn vì nó gọi / bin / sh cho mỗi thư mục. Bạn có thể kiểm tra điều này với strace -fc script. Phiên bản của bạn thực hiện thêm khoảng 70% các cuộc gọi hệ thống. +1 cho mã ngắn hơn :-)
Thor

1
lấy cảm hứng từ điều này; được sắp xếp theo filecount:find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
mnagel

7
find . -type f | cut -d"/" -f2 | uniq -c

Liệt kê một thư mục và tệp trong thư mục hiện tại với số lượng tệp được tìm thấy bên dưới. IMO nhanh chóng và hữu ích. (tập tin hiển thị với số 1).


1
Làm thế nào về một lời giải thích nhỏ về cách nó đang làm việc? :)
C0deDaedalus

1
thật sự cảm ơn! Bạn có thể muốn thêm | sort -rnđể sắp xếp các thư mục con theo số lượng tệp.
Dennis Golomazov

1

Sử dụng find chắc chắn là cách tốt nhất nếu bạn muốn đếm đệ quy, nhưng nếu bạn chỉ muốn đếm số lượng tệp trực tiếp trong một thư mục nhất định:

ls dir1 | wc -l


Tôi không muốn làm điều này cho mỗi 1000 thư mục tôi đã có ở đó ...
jldupont

Sau đó sử dụng xargs. ls -d */ | xargs -n1 ls | wc -l(Tuy nhiên, hãy sử dụng câu trả lời bạn đã chấp nhận nếu nó đã hoạt động! Đây chỉ là Và Bây giờ bạn biết.)
jrajav

đề xuất của bạn không hiển thị bất kỳ kết quả nào trong nhiều giây trong khi câu trả lời tôi chấp nhận.
jldupont

@jrajav phương pháp này hoàn toàn thất bại đối với các thư mục có khoảng trắng trong đó. Đây là lý do tại sao findrất quan trọng. (hãy để một mình -print0xargs -0, đã được Scott chỉ ra trong câu trả lời khác)
cú pháp

1
find . -mindepth 1 -type d -print0 | xargs -0 -I{} sh -c 'printf "%4d : %s\n" "$(find {} -type f | wc -l)" "{}"'

Tôi cần thường xuyên phải đếm số lượng tệp trong thư mục con của tôi và sử dụng lệnh này. Tôi thích số lượng xuất hiện đầu tiên.


0

Những gì tôi sử dụng ... Điều này tạo ra một mảng của tất cả các thư mục con trong thư mục bạn cung cấp làm tham số. In thư mục con và số lượng của thư mục con đó cho đến khi tất cả các thư mục con được xử lý.

#!/bin/bash    
directories=($(/bin/ls -l $1 | /bin/grep "^d" | /usr/bin/awk -F" " '{print $9}'))

for item in ${directories[*]}
    do
        if [ -d "$1$item" ]; then
            echo "$1$item"
            /bin/ls $1$item | /usr/bin/wc -l
        fi
    done

0

Bạn có thể sử dụng mã python này. Khởi động trình thông dịch bằng cách chạy python3và dán này:

folder_path = '.'
import os, glob
for folder in sorted(glob.glob('{}/*'.format(folder_path))):
    print('{:}: {:>8,}'.format(os.path.split(folder)[-1], len(glob.glob('{}/*'.format(folder)))))

Hoặc một phiên bản đệ quy cho số lượng lồng nhau:

import os, glob
def nested_count(folder_path, level=0):
    for folder in sorted(glob.glob('{}/'.format(os.path.join(folder_path, '*')))):
        print('{:}{:}: {:,}'.format('    '*level, os.path.split(os.path.split(folder)[-2])[-1], len(glob.glob(os.path.join(folder, '*')))))
        nested_count(folder, level+1)
nested_count('.')

Ví dụ đầu ra:

>>> figures: 5
>>> misc: 1
>>> notebooks: 5
>>>     archive: 65
>>>     html: 12
>>>     py: 12
>>>     src: 14
>>> reports: 1
>>>     content: 6
>>> src: 1
>>>     html_download: 1
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.