Знайти 50 найкращих каталогів, що містять найбільше файлів / каталогів на їхньому першому рівні?


21

Як я можу findстворити список каталогів, що містять найбільшу кількість файлів. Я хотів би, щоб список був від найвищого до найнижчого. Мені б хотілося, щоб список перейшов на глибину 1 рівня, і я зазвичай виконував цю команду вгорі моєї файлової системи, тобто /.


Різне запитання (насправді те саме, але задається по-різному), але чи не вирішила б також ваше питання? unix.stackexchange.com/questions/117093/…
Патрік

Також пов’язані - stackoverflow.com/questions/15216370/… . Це те, на чому я грунтувався на своїй оригінальній відповіді на питання про inode, хоча я вважаю, що мій підхід пропонує деякі вдосконалення над тими, що існують.
Graeme

@Patrick - це завантажений Q просто для розміщення Graemes A. Щоправда, біти закопані в інших Q's, але це повинно було вивести цей біт, щоб на нього можна було посилатися вперед.
slm

@slm Тоді я дійсно не розумію, чому це не дублікат. Його відповідь, здається, є лише опрацюванням відповіді на інше питання. Отже, зараз у нас є 3 запитання до тієї ж речі. Я думаю, що відповідь на моєму посиланні теж чистіша. Якщо запустити оболонку для кожного знайденого каталогу, просто брудно.
Патрік

1
@Patrick, я переробив відповідь, щоб рішення GNU не запускало нову оболонку для кожного каталогу. Хоча зауважте, що це стандартне рішення для обробки будь-якого імені файлів на портативному рівні.
Graeme

Відповіді:


17

Використання інструментів 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

Для цього використовуються дві findкоманди. Перший знаходить каталоги та передає їх у whileцикл, виконує наступну знахідку для кожного каталогу. Другий перераховує всі дочірні файли / каталоги першого рівня, при цьому grepпідраховує їх. grepДозволяє -print0використовуватися з другої знахідкою , так як wcне має -zеквівалента. Це зупиняє, щоб назви файлів з новим рядком рахувалися двічі (хоча використання wcта жодне значення -print0не мали б великої різниці).

Результат другого findрозміщується в аргументі echoтак, і ім'я каталогів легко розміщується в одному рядку ( $(..)конструкція автоматично обрізає новий рядок в кінці grep). Потім рядки сортуються за кількістю та 50 найбільших цифр, показаними за допомогою head.

Зауважте, що це також буде включати каталоги верхніх рівнів точок монтажу. Простий спосіб подолати це - скористатися прив'язкою, а потім скористатися каталогом версії. Зробити це:

sudo mount --bind / /mnt

Більш портативне рішення використовує інший екземпляр оболонки для кожного каталогу (також тут відповіли ):

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

Вибірка зразка:

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

ОНОВЛЕННЯ: Я все це робив нижче, що класно, але я придумав кращий спосіб сортування каталогів за допомогою inode:

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

І якщо ви хочете залишитися в тій же файловій системі, ви зробите:

du --inodes -xS

Ось кілька прикладів виводу:

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

ЗАРАЗ З LS:

Кілька людей згадували, що не мають оновлених базових програм, а параметр --inodes їм недоступний. Отже, ось:

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

Це дає мені майже однакові результати duкоманди:

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:

Я думаю, що includeріч просто залежить від того, який каталог спочатку виглядає програма - тому що вони однакові файли та жорстке посилання. Ніби як річ вище. Я можу помилитися з цього приводу - і я вітаю виправлення ...

Основним методом цього є те, що я замінюю кожну lsфайлову назву файлу, що містить ім'я каталогів, в sed.наступному від цього ... Ну, я трохи нечіткий сам. Я впевнений, що це точно підраховує файли, як ви бачите тут:

% _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

Складіть тестовий каталог:

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

Деякі довідники для дітей:

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

Створіть кілька файлів:

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

Деякі жорсткі посилання:

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

Подивіться на жорсткі посилання:

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

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

Вони рахуються поодинці, але перейдіть по одному каталогу вгору ...

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

Потім я запустив свій запущений сценарій знизу і:

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

І Graeme:

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

Тому я думаю, що це свідчить про те, що єдиний спосіб підрахунку inode - це inode. А тому що підрахунок файлів означає підрахунок inode, ви не можете подвоїти підрахунок удвічі - точний підрахунок файлів inodes неможливо перерахувати більше одного разу.

СТАРИЙ:

Я знаходжу це швидше, і це портативно:

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

Це не обов’язково -execдля кожного каталогу - він використовує лише один shпроцес ell і один find. Я повинен отримати set -- $globправо все ж включати .hiddenфайли та все інше, але це дуже близько і дуже швидко. Ви просто cdвходили б у ваш кореневий каталог для перевірки та виходу.

Ось зразок мого виходу з /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

Я також використовую sedвнизу там, щоб підрізати його до топ-50 результатів. headбуло б швидше, звичайно, але я також обрізаю кожен рядок, якщо це необхідно:

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

Це, правда, сира, але це була думка. Ще один сирий пристрій, який я використовую, - це скидання 2>stderrяк для, так findі cdдля нього 2>/dev/null. Це просто чистіше, ніж дивитися на помилки дозволів для каталогів, які я не можу читати без кореневого доступу - можливо, я повинен це вказати find. Ну, це незавершена робота.

Гаразд, тому я виправив кульки оболонки так:

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

Я насправді збирався задати питання про те, як це можна зробити, але, коли я набирав назву питання, сайт вказав мені на запропоноване споріднене питання, де, ось ось, Стефан вже зважив . Так що було зручно. Мабуть, [^.],хоча він добре підтримується, не є портативним, і вам доведеться використовувати те, що !bang.я знайшов, що в коментарі Стефана є.

У будь-якому випадку, очевидно, недостатньо лише затягувати приховані файли. Тому мені доводиться setдвічі, щоб уникнути пошуку позицій для буквального $glob. Але, схоже, це зовсім не впливає на продуктивність, і він надійно додає кожен файл у каталозі.


@Graeme Ви знаєте, жодне з наших рішень насправді не обробляє inode. Багато цих файлів, які ми перелічуємо, ймовірно, важко пов'язані між собою. Я думаю, що я міг би зробити це за допомогою ls -iі ... я думаю ... напевно grep... можливо ... можливо, ви використовуєте, -xdev,що є початком ... uniqі sort?
mikeserv

Яку версію duви працюєте? У мене duнемає --inodesможливості.
Патрік

@Patrick - можливо, хочу оновити, але я оновив публікацію.
mikeserv

Це особливість кровотоку :-) Я бігаю 8.21. Схоже, це було додано 2013-07-27: git.savannah.gnu.org/gitweb/…
Патрік

Крім того, якщо ви не заперечуєте, чи можете ви написати це питання з цього питання . Я не думаю, що прийму це, оскільки це не дуже портативно, але я підтримаю заяву, і було б непогано мати ще одне рішення питання.
Патрік

1

Чому б не використовувати щось на кшталт KDirStat Хоча він був спочатку написаний для KDE, але він добре працює з GNOME aswell, він дає найкращий перегляд кількості файлів / dir та відповідного використання в GUI


1
Шукаємо метод командного рядка.
slm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.