最初のレベルで最もファイル/ディレクトリを含む上位50のディレクトリを見つけますか?


21

find最も多くのファイルを含むディレクトリのリストを生成するためにどのように使用できますか。リストを最高から最低にしたいと思います。リストの深さを1レベルだけにしたいので、通常はこのコマンドをファイルシステムの最上部、つまりから実行します/


別の質問(実際には同じですが、異なる質問があります)が、答えもあなたの質問を解決しませんか?unix.stackexchange.com/questions/117093/…–
パトリック

また、関連- stackoverflow.com/questions/15216370/...を。私のアプローチはそこにあるものよりもいくつかの改善を提供すると思いますが、これは、iノードの質問に基づいて私の元の答えを基にしたものです。
グレアム14

@Patrick-これはGraemes Aを収容するためだけのロードされたQです。ビットは他のQのAに埋もれていますが、これはこのビットを引き出して先に参照できるようにするためです。
slm

@slmそれから、なぜこれが複製ではないのか本当に分かりません。彼の答えは、別の質問に対する答えの詳細にすぎないようです。そのため、同じことに対して3つの質問があります。リンクの答えもきれいだと思います。見つかったすべてのディレクトリのシェルを起動するだけで汚い感じ。
パトリック14

1
@Patrick、私は答えを作り直したので、GNUソリューションはすべてのディレクトリに対して新しいシェルを開始しません。ただし、これは任意のファイル名を移植可能に処理するための標準的なソリューションです。
グレアム14

回答:


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

これは2つのfindコマンドを使用します。最初にディレクトリを検索し、それらをwhileループにパイプして、各ディレクトリの次の検索を実行します。2番目は、grepそれらをカウントしながら、最初のレベルのすべての子ファイル/ディレクトリをリストします。にはないため、2番目の検索で使用grepできます。-print0wc-z同等のものを。これにより、改行を含むファイル名が2回カウントされるのを防ぎます(ただし、使用wcしても-print0大した違いはありません)。

2番目の結果は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 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

それらは単独でカウントされますが、1つ上のディレクトリに移動します...

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

次に、下から実行スクリプトを実行し、

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

そしてグレームズ:

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

したがって、これは、iノードをカウントする唯一の方法がiノードによることであることを示していると思います。また、ファイルのカウントはiノードのカウントを意味するため、iノードを二重にカウントすることはできません。ファイルを正確にカウントするために、iノードを複数回カウントすることはできません。

古い:

私はこれをより速く見つけ、ポータブルです:

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すべてのディレクトリに対応する必要はありません。1つのshellプロセスと1 つの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
...

確かに粗野ですが、それは考えでした。私が使用するもう1つの粗雑なデバイスは2>stderr、両方findcdにダンプすることです2>/dev/null。ルートアクセスなしでは読めないディレクトリのパーミッションエラーを見るよりもきれいです-おそらくそれを指定する必要がありますfind。まあ、それは進行中の作業です。

わかりましたので、このようにシェルグロブを修正しました。

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

私は実際にそれを行うことができる方法についての質問をするつもりだったが、私は質問のタイトルを入力したとして、サイトがに私を指摘提案し、関連する質問、驚くなかれ、ステファンはすでにしていた中で計量します。とても便利でした。どうやら[^.],十分にサポートされているようですが、移植性がなく、使用する必要が!bang.あります。そこにあるStephaneのコメントでそれを見つけました。

とにかく、明らかに隠しファイルを取り込むだけでは十分ではありませんでした。したがってset、リテラルの位置を検索することを避けるために2回行う必要があり$globます。それでも、パフォーマンスにはまったく影響しないようで、ディレクトリ内のすべてのファイルを確実に追加します。


@Graemeご存知のように、どちらのソリューションも実際にはiノードを処理していません。リストしているこれらのファイルの多くは、相互にハードリンクされている可能性があります。私はこれをls -i…でできると思いますgrep...たぶん...おそらく...多分-あなたは-xdev,どちらを使用していますか... uniqそしてsort
mikeserv 14

どのバージョンduを実行していますか?私にdu--inodes選択肢がありません。
パトリック14

@Patrick-更新したいかもしれません-しかし、私は投稿を更新しました。
mikeserv 14

これは最先端の機能です:-) 8.21を実行しています。追加されたように見える2013-07-27:git.savannah.gnu.org/gitweb/…–
パトリック

また、気にしない場合は、この質問に投稿してください。あまりポータブルではないので、私はそれを受け入れるつもりはありませんが、私は賛成します、そして、質問に別の解決策があることは素晴らしいことです。
パトリック14

1

KDirStatのようなものを使用しないのはなぜですか。元はKDE向けに書かれたものですが、GNOMEでも正常に動作します。


1
コマンドライン方式を探しています。
slm
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.