가장 많은 파일/디렉터리를 포함하는 첫 번째 수준의 상위 50개 디렉터리를 찾으십니까?

가장 많은 파일/디렉터리를 포함하는 첫 번째 수준의 상위 50개 디렉터리를 찾으십니까?

find최대 파일 수를 포함하는 디렉토리 목록을 생성하는 방법 . 목록이 가장 높은 것부터 낮은 것 순으로 정렬되기를 원합니다. 나는 목록의 깊이가 1레벨이 되기를 원하며 일반적으로 파일 시스템의 최상위에서 이 명령을 실행합니다 /.

답변1

업데이트: 나는 아래의 모든 작업을 수행했습니다. 이는 훌륭하지만 다음을 사용하여 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와 함께:

몇몇 사람들은 최신 coreutils가 없고 --inodes 옵션을 사용할 수 없다고 언급했습니다. 따라서 이것은 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

이는 다음 명령과 거의 동일한 결과를 제공합니다 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

Dudemore

% 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를 두 번 이상 계산할 수 없습니다.

오래된:

나는 이것이 더 빠르고 이식성이 있다는 것을 알았습니다.

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모든 디렉터리에 대해 그럴 필요는 없습니다. 단지 하나 의 shell 프로세스와 하나 의 find. 루트 디렉토리로 가서 확인하면 됩니다.set -- $glob.hiddencd

다음은 내 실행 결과의 예입니다 /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하는 것 입니다 . 루트 액세스 없이는 읽을 수 없는 디렉토리에 대한 권한 오류를 보는 것보다 더 깔끔합니다. 아마도 이를 로 지정해야 할 것입니다 .findcd2>/dev/nullfind

좋습니다. 그래서 저는 쉘 글로브를 다음과 같이 수정했습니다:

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

사실 이 작업을 수행하는 방법에 대해 질문하려고 했으나 질문 제목을 입력하자 사이트에서 다음을 가리켰습니다.추천 관련 질문보시다시피 스티븐은계량. 그래서 이것은 매우 편리합니다. 확실히, [^.],잘 지원되면서도아니요!bang.휴대용, Stephen의 의견에서 찾은 것을 사용해야 합니다 .

그럼에도 불구하고 단순히 숨겨진 파일을 가져오는 것만으로는 충분하지 않습니다. 그래서 setposition 에서 리터럴을 검색하지 않으려면 두 번 수행해야 합니다 $glob. 그래도 성능에는 전혀 영향을 미치지 않는 것 같고 디렉터리의 모든 파일을 안정적으로 추가합니다.

답변2

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동등한 항목이 없으므로 두 번째 조회와 함께 사용할 수 있습니다 . 이렇게 하면 개행 문자가 포함된 파일 이름이 두 번 계산되는 것을 방지할 수 있습니다(비록 및 no를 사용하더라도 큰 차이는 없습니다).-print0wc-zwc-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

답변3

KDirStat과 같은 것을 사용하면 어떨까요? 원래는 KDE용으로 작성되었지만 GNOME에서도 잘 작동합니다. GUI에서 파일/디렉토리 수와 각각의 사용법을 가장 잘 볼 수 있습니다.

답변4

이를 위해서는 zshglob 한정자가 필요합니다.

print -rC1 -- **/*(ND/nOe['(){REPLY=$#;} $REPLY/*(NDoN)'][1,50])
  • print -rC1 --: s열의 print매개변수r1 C
  • **/*:recursive wildcard: 임의 개수의 하위 디렉터리에 있는 모든 파일
  • (N...):glob 한정자는 glob 확장을 더욱 한정합니다.
  • N: N울글롭. 일치하는 항목이 없어도 불평하지 않습니다.
  • D: D오글롭. 또한 파일 숨기기를 고려하십시오.
  • nOe[code]: 평가액을 기준으로 역순으로 주문합니다 O.necode
  • 여기의 코드는 에 인수 수를 저장하는 익명 함수에 확장명을 전달하여 $REPLY디렉터리의 파일 수를 설정합니다 .$REPLY/*(NDoN)$REPLY
  • [1,50]: 처음 50개만 반환됩니다.

관련 정보