Tìm 50 thư mục hàng đầu chứa hầu hết các tệp / thư mục ở cấp độ đầu tiên của họ?


21

Làm cách nào tôi có thể sử dụng findđể tạo danh sách các thư mục chứa số lượng tệp nhiều nhất. Tôi muốn danh sách từ cao nhất đến thấp nhất. Tôi chỉ muốn danh sách đi sâu 1 cấp và tôi thường chạy lệnh này từ đầu hệ thống tệp của mình, tức là /.


Câu hỏi khác nhau (thực ra giống nhau nhưng được hỏi khác nhau), nhưng câu trả lời có giải quyết được câu hỏi của bạn không? unix.stackexchange.com/questions/117093/ Kẻ
Patrick

Cũng liên quan - stackoverflow.com/questions/15216370/ . Đây là những gì tôi dựa trên câu trả lời ban đầu của mình cho câu hỏi inode, mặc dù tôi nghĩ cách tiếp cận của tôi cung cấp một số cải tiến so với câu hỏi ở đó.
Graeme

@Patrick - đây là một Q được nạp chỉ để chứa Graeme A. Đúng là các bit được chôn trong các chữ A khác của Q, nhưng điều này là để đưa bit này ra ngoài để nó có thể được tham chiếu về phía trước.
slm

@slm Sau đó, tôi thực sự không hiểu tại sao điều này không phải là một bản sao. Câu trả lời của ông dường như chỉ là một câu trả lời cho một câu hỏi khác. Vì vậy, bây giờ chúng tôi có 3 câu hỏi cho cùng một điều. Tôi nghĩ rằng câu trả lời trên liên kết của tôi là sạch hơn. Khởi chạy một shell cho mọi thư mục tìm thấy chỉ cảm thấy bẩn.
Patrick

1
@Patrick, tôi đã làm lại câu trả lời để giải pháp GNU không khởi động trình bao mới cho mọi thư mục. Mặc dù lưu ý rằng đây là giải pháp tiêu chuẩn để xử lý bất kỳ tên tệp nào.
Graeme

Câu trả lời:


17

Sử dụng các công cụ GNU:

find / -xdev -type d -print0 |
  while IFS= read -d '' dir; do
    echo "$(find "$dir" -maxdepth 1 -print0 | grep -zc .) $dir"
  done |
  sort -rn |
  head -50

Cái này dùng hai find lệnh. Đầu tiên tìm thấy các thư mục và dẫn chúng đến một whilevòng lặp chạy tìm kiếm tiếp theo cho mỗi thư mục. Thứ hai liệt kê tất cả các tập tin / thư mục con ở cấp độ đầu tiên trong khi grepđếm chúng. Các grepphép -print0để được sử dụng với tìm thứ hai kể từ khi wckhông có một -ztương đương. Điều này ngăn tên tập tin với một dòng mới được tính hai lần (mặc dù sử dụng wc-print0không tạo ra nhiều khác biệt).

Kết quả của lần thứ hai findđược đặt trong đối số để echonó và tên thư mục có thể dễ dàng được đặt trên cùng một dòng ( $(..)cấu trúc sẽ tự động cắt đường mới ở cuối grep). Các dòng sau đó được sắp xếp theo số và 50 số lớn nhất được hiển thị với head.

Lưu ý rằng điều này cũng sẽ bao gồm các thư mục cấp cao nhất của các điểm gắn kết. Một cách đơn giản để giải quyết vấn đề này là sử dụng mount mount và sau đó sử dụng thư mục của mount. Để làm điều này:

sudo mount --bind / /mnt

Một giải pháp di động hơn sử dụng một thể hiện shell khác nhau cho mỗi thư mục (cũng được trả lời ở đây ):

find / -xdev -type d -exec sh -c '
  echo "$(find "$0" | grep "^$0/[^/]*$" | wc -l) $0"' {} \; |
  sort -rn |
  head -50

Đầu ra mẫu:

9225 /var/lib/dpkg/info
6322 /usr/share/qt4/doc/html
4927 /usr/share/man/man3
2301 /usr/share/man/man1
2097 /usr/share/doc
2097 /usr/bin
1863 /usr/lib/x86_64-linux-gnu
1679 /var/cache/apt/archives
1628 /usr/share/qt4/doc/src/images
1614 /usr/share/qt4/doc/html/images
1308 /usr/share/scilab/modules/overloading/macros
1083 /usr/src/linux-headers-3.13-1-common/include/linux
1071 /usr/src/linux-headers-3.13-1-amd64/include/config
847 /usr/include/qt4/QtGui
774 /usr/include/qt4/Qt
709 /usr/share/man/man8
616 /usr/lib
611 /usr/share/icons/oxygen/32x32/actions
608 /usr/share/icons/oxygen/22x22/actions
598 /usr/share/icons/oxygen/16x16/actions
579 /usr/share/bash-completion/completions
574 /usr/share/icons/oxygen/48x48/actions
570 /usr/share/vim/vim74/syntax
546 /usr/share/scilab/modules/m2sci/macros/sci_files
531 /usr/lib/i386-linux-gnu/wine/wine
530 /usr/lib/i386-linux-gnu/wine/wine/fakedlls
496 /etc/ssl/certs
457 /usr/share/mime/application
454 /usr/share/man/man2
450 /usr/include/qt4/QtCore
443 /usr/lib/python2.7
419 /usr/src/linux-headers-3.13-1-common/include/uapi/linux
413 /usr/share/fonts/X11/misc
413 /usr/include/linux
375 /usr/share/man/man5
374 /usr/share/lintian/overrides
372 /usr/share/cmake-2.8/Modules
370 /usr/share/fonts/X11/75dpi
370 /usr/share/fonts/X11/100dpi
356 /usr/share/icons/gnome/24x24/actions
356 /usr/share/icons/gnome/22x22/actions
356 /usr/share/icons/gnome/16x16/actions
353 /usr/share/icons/gnome/48x48/actions
353 /usr/share/icons/gnome/32x32/actions
341 /usr/lib/ghc/ghc-7.6.3
326 /usr/sbin
324 /usr/share/scilab/modules/compatibility_functions/macros
324 /usr/share/scilab/modules/cacsd/macros
320 /usr/share/terminfo/a
319 /usr/share/i18n/locales

11

CẬP NHẬT: Tôi đã làm tất cả những điều đó dưới đây, điều này thật tuyệt, nhưng tôi đã nghĩ ra một cách tốt hơn để sắp xếp các thư mục bằng cách sử dụng inode:

du --inodes -S | sort -rh | sed -n \
        '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'

Và nếu bạn muốn ở trong cùng một hệ thống tập tin bạn làm:

du --inodes -xS

Dưới đây là một số ví dụ đầu ra:

15K     /usr/share/man/man3
4.0K    /usr/lib
3.6K    /usr/bin
2.4K    /usr/share/man/man1
1.9K    /usr/share/fonts/75dpi
...
519     /usr/lib/python2.7/site-packages/bzrlib
516     /usr/include/KDE
498     /usr/include/qt/QtCore
487     /usr/lib/modules/3.13.6-2-MANJARO/build/include/config
484     /usr/src/linux-3.12.14-2-MANJARO/include/config

BÂY GIỜ VỚI LS:

Một số người đề cập rằng họ không có coreutils cập nhật và tùy chọn --inodes không có sẵn cho họ. Vì vậy, đây là ls:

sudo ls -AiR1U ./ | 
sed -rn '/^[./]/{h;n;};G;
    s|^ *([0-9][0-9]*)[^0-9][^/]*([~./].*):|\1:\2|p' | 
sort -t : -uk1.1,1n |
cut -d: -f2 | sort -V |
uniq -c |sort -rn | head -n10

Điều này mang lại cho tôi khá nhiều kết quả giống hệt với du lệnh:

DU:

15K     /usr/share/man/man3
4.0K    /usr/lib
3.6K    /usr/bin
2.4K    /usr/share/man/man1
1.9K    /usr/share/fonts/75dpi
1.9K    /usr/share/fonts/100dpi
1.9K    /usr/share/doc/arch-wiki-markdown
1.6K    /usr/share/fonts/TTF
1.6K    /usr/share/dolphin-emu/sys/GameSettings
1.6K    /usr/share/doc/efl/html

LS:

14686   /usr/share/man/man3:
4322    /usr/lib:
3653    /usr/bin:
2457    /usr/share/man/man1:
1897    /usr/share/fonts/100dpi:
1897    /usr/share/fonts/75dpi:
1890    /usr/share/doc/arch-wiki-markdown:
1613    /usr/include:
1575    /usr/share/doc/efl/html:
1556    /usr/share/dolphin-emu/sys/GameSettings:

Tôi nghĩ rằng include điều này chỉ phụ thuộc vào thư mục mà chương trình nhìn vào đầu tiên - bởi vì chúng là các tệp giống nhau và được liên kết cứng. Kinda như điều trên. Tôi có thể sai về điều đó mặc dù - và tôi hoan nghênh sự điều chỉnh ...

Phương pháp cơ bản cho vấn đề này là tôi thay thế mỗi lstên tệp bằng tên thư mục chứa trong sed.Tiếp theo từ đó ... Chà, bản thân tôi hơi mờ. Tôi khá chắc chắn rằng nó đếm chính xác các tệp, như bạn có thể thấy ở đây:

% _ls_i ~/test
> 100 /home/mikeserv/test/realdir
>   2 /home/mikeserv/test
>   1 /home/mikeserv/test/linkdir

DU DEMO

% du --version
> du (GNU coreutils) 8.22

Tạo một thư mục thử nghiệm:

% mkdir ~/test ; cd ~/test
% du --inodes -S
> 1       .

Một số thư mục trẻ em:

% mkdir ./realdir ./linkdir
% du --inodes -S
> 1       ./realdir
> 1       ./linkdir
> 1       .

Tạo một số tệp:

% printf 'touch ./realdir/file%s\n' `seq 1 100` | . /dev/stdin
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

Một số liên kết cứng:

% printf 'n="%s" ; ln ./realdir/file$n ./linkdir/link$n\n' `seq 1 100` | 
    . /dev/stdin
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

Nhìn vào các liên kết cứng:

% cd ./linkdir
% du --inodes -S
> 101

% cd ../realdir
% du --inodes -S
> 101

Họ được tính một mình, nhưng đi lên một thư mục ...

% cd ..
% du --inodes -S
> 101     ./realdir
> 1       ./linkdir
> 1       .

Sau đó, tôi chạy tập lệnh đã chạy của tôi từ bên dưới và:

> 100     /home/mikeserv/test/realdir
> 100     /home/mikeserv/test/linkdir
> 2       /home/mikeserv/test

Và Graeme:

> 101 ./realdir
> 101 ./linkdir
> 3 ./

Vì vậy, tôi nghĩ rằng điều này cho thấy cách duy nhất để đếm inodes là inode. Và bởi vì đếm các tệp có nghĩa là đếm các nút, bạn không thể đếm gấp đôi các nút - để đếm các tệp chính xác, các nút không thể được đếm nhiều lần.

CŨ:

Tôi thấy cái này nhanh hơn và nó có thể mang theo được:

sh <<-\CMD
    { echo 'here='"$PWD"
        printf 'cd "${here}/%s" 2>/dev/null && {
                set -- 
                for glob in ".[!.]*" "[!.]*" ; do
                    set -- $glob "$@" && 
                        [ -e "./$1" ] || shift
                done    
                printf "%%s\\t%%s\\n" $# "$PWD"
        }\n' $( find . -depth -type d 2>/dev/null )
    } | . /dev/stdin |
    sort -rn | 
    sed -n \
        '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'
CMD

Nó không phải -execcho mọi thư mục - nó chỉ sử dụng một shquá trình ell và một find. Tôi phải có set -- $globquyền bao gồm .hiddencác tệp và tất cả các tệp khác, nhưng nó rất gần và rất nhanh. Bạn sẽ chỉ cần cdvào bất cứ thứ gì thư mục gốc của bạn sẽ được kiểm tra và tắt đi.

Đây là một mẫu đầu ra của tôi chạy từ /usr:

14684   /usr/share/man/man3
4322    /usr/lib
3650    /usr/bin
2454    /usr/share/man/man1
1897    /usr/share/fonts/75dpi
...
557     /usr/share/gtk-doc/html/gtk3
557     /usr/share/doc/elementary/latex
539     /usr/lib32/wine/fakedlls
534     /usr/lib/python2.7/site-packages/bzrlib
500     /usr/lib/python3.3/test

Tôi cũng sử dụng sedở dưới cùng để cắt nó thành 50 kết quả hàng đầu. headtất nhiên sẽ nhanh hơn, nhưng tôi cũng cắt từng dòng nếu cần thiết:

...   
159     /home/mikeserv/.config/hom...hhkdoolnlbekcfllmednbl/4.30_0/plugins
154     /home/mikeserv/.config/hom...odhpcledpamjachpmelml/1.3.11_0/js/ace
...

Đó là thô thiển, thừa nhận, nhưng đó là một suy nghĩ. Một thiết bị thô khác tôi sử dụng là bán phá giá 2>stderrcho cả hai findcdvào 2>/dev/null. Nó chỉ sạch hơn là nhìn vào các lỗi cấp phép cho các thư mục mà tôi không thể đọc mà không có quyền truy cập root - có lẽ tôi nên chỉ định điều đó find. Vâng, đó là một công việc đang tiến triển.

Ok, vì vậy tôi đã sửa chữa các khối vỏ như thế này:

for glob in ".[!.]*" "[!.]*" ; do
    set -- $glob "$@" && 
        [ -e "./$1" ] || shift
done    

Tôi thực sự sẽ hỏi một câu hỏi về cách nó có thể được thực hiện, nhưng khi tôi đang gõ tiêu đề câu hỏi, trang web chỉ cho tôi một câu hỏi liên quan được đề xuất trong đó, lo và kìa, Stephane đã cân nhắc . Vì vậy, đó là thuận tiện. Rõ ràng [^.],trong khi được hỗ trợ tốt, không phải là di động và bạn phải sử dụng!bang. Tôi thấy rằng trong nhận xét của Stephane ở đó.

Dù sao, chỉ cần kéo vào các tập tin ẩn là không đủ, rõ ràng. Vì vậy, tôi phải sethai lần để tránh tìm kiếm vị trí cho nghĩa đen $glob. Tuy nhiên, nó dường như không ảnh hưởng đến hiệu suất, và nó đáng tin cậy thêm mọi tệp trong thư mục.


@Graeme Bạn biết đấy, cả hai giải pháp của chúng tôi đều không thực sự xử lý các nút. Rất nhiều tệp chúng tôi liệt kê có khả năng liên kết cứng với nhau. Tôi nghĩ rằng tôi có thể làm điều này với ls -ivà ... tôi đoán ... có lẽ grep... có lẽ - tốt, bạn đang sử dụng -xdev,đó là một sự khởi đầu ... uniqsort?
mikeerv

Phiên bản dunào bạn đang chạy? My dukhông có --inodeslựa chọn.
Patrick

@Patrick - có thể muốn cập nhật - nhưng tôi đã cập nhật bài viết.
mikeerv

Đó là một tính năng vượt trội :-) Tôi đang chạy 8.21. Có vẻ như nó đã được thêm vào 2013-07-27: git.savannah.gnu.org/gitweb/ Kẻ
Patrick

Ngoài ra, nếu bạn không phiền, bạn có thể đăng nó lên câu hỏi này không . Tôi không nghĩ rằng tôi sẽ chấp nhận nó vì nó không dễ mang theo, nhưng tôi sẽ nâng cao, và thật tuyệt khi có một giải pháp khác cho câu hỏi này.
Patrick

1

Tại sao không sử dụng cái gì đó như KDirStat Mặc dù ban đầu nó được viết cho KDE nhưng nó hoạt động tốt với Gnome. Nó cung cấp cho bạn cái nhìn tốt nhất về số lượng tệp / thư mục và cách sử dụng tương ứng trong GUI


1
Tìm kiếm phương pháp dòng lệnh.
slm
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.