첫 번째 레벨에서 가장 많은 파일 / 디렉토리를 포함하는 상위 50 개 디렉토리를 찾으십니까?


21

find가장 많은 파일을 포함하는 디렉토리 목록을 생성하는 데 어떻게 사용할 수 있습니까 ? 목록이 가장 높은 것부터 가장 낮은 것까지 싶으면합니다. 리스팅이 1 레벨 깊이로 가고 싶고 일반적으로 파일 시스템의 맨 위에서이 명령을 실행합니다 /.


다른 질문 (실제로 동일하지만 다르게 질문)이지만 대답이 귀하의 질문을 해결하지 못합니까? unix.stackexchange.com/questions/117093/…
Patrick Patrick

또한 관련 - stackoverflow.com/questions/15216370/...을 . 이것이 내가 inode 질문에 대한 원래의 대답을 기반으로 한 것이지만, 내 접근법은 거기에 비해 개선 된 점이 있다고 생각합니다.
Graeme

@ 패트릭 (Patrick)-Graemes A를 수용하기 위해로드 된 Q입니다. 비트는 다른 Q의 A에 묻혀 있지만이 비트를 가져와 앞으로 참조 할 수 있도록했습니다.
slm

@slm 그렇다면 왜 이것이 중복되지 않는지 알 수 없습니다. 그의 대답은 다른 질문에 대한 정교함을 나타내는 것 같습니다. 이제 우리는 같은 것에 대해 3 가지 질문을합니다. 내 링크의 답변도 깨끗하다고 ​​생각합니다. 발견 된 모든 디렉토리에 대해 쉘을 시작하면 더러워집니다.
Patrick

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와 함께 지금 :

몇몇 사람들은 최신 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명령 과 거의 동일한 결과를 제공합니다 .

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 --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 's :

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

따라서 이것이 inode를 계산하는 유일한 방법은 inode에 의한 것임을 보여줍니다. 그리고 파일을 세는 것은 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모든 디렉토리 에 대해 필요한 것은 아닙니다 . sh하나의 프로세스와 하나의 프로세스 만 사용합니다 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
...

물론, 그것은 조잡하지만 생각이었습니다. 또 다른 원유 장치 I 사용은 덤핑 2>stderr모두 findcd2>/dev/null. 루트 액세스없이 읽을 수없는 디렉토리에 대한 권한 오류를 보는 것보다 더 깨끗합니다 find. 아마도이를 지정해야합니다 . 글쎄, 그것은 진행중인 작업입니다.

좋아, 그래서 나는 다음과 같이 껍질 globs를 고쳤다.

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

나는 실제로 그것을 할 수있는 방법에 대한 질문을하려고했지만, 나는 질문 제목에 입력되었을 때 사이트는 저를 지적 제안 관련 질문 , 보라와 보라, 스테판 이미 한 에 무게 . 그래서 편리했습니다. 분명히 [^.],잘 지원되는 동안 휴대용 이 아니며!bang. Stephane의 의견에서 찾은 것을 사용해야합니다 .

어쨌든 숨겨진 파일을 가져 오는 것만으로는 충분하지 않습니다. 따라서 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/…
Patrick

또한 마음에 들지 않으면 이 질문 에 게시 할 수 있습니다 . 나는 그것이 이식성이 좋지 않기 때문에 그것을 받아 들일 것이라고 생각하지 않지만 나는 투표 할 것이고, 질문에 대한 다른 해결책을 갖는 것이 좋을 것입니다.
Patrick

1

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


1
명령 행 방법을 찾고 있습니다.
slm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.