web-dev-qa-db-ja.com

ホームディレクトリ内のファイルとディレクトリの総数をカウントするスクリプトを作成して表示するにはどうすればよいですか。

forループでそれを実行したいと思います。これは私がこれまでに思いついたもので、機能しません。

for home in /home/ {.,/}*; do echo "$home"; done

可能であれば、これを非再帰的に行いたいと思います。

3
David Prentice

やりたいことをほぼ実行する上位レベルのコマンドは多数ありますが、これはシェルスクリプトで同じことを行う方法の優れたデモです。これは、/bin/shがあるanyシステムで機能するはずです。他のコマンドには依存しません。

このスクリプトを任意のファイル名で保存し、sh ./whatever_you_named_itと入力して実行できます。

これをファイルのリストファイルのカウントの2つのセクションに分割しました。ファイルを再帰的にリストすることは最も複雑ですが、リストを取得すると、簡単にカウントできます。

ファイルのリスト

このスクリプトは、ホームディレクトリまたはパラメータとして受け取るディレクトリの下にあるすべてのファイルとディレクトリを再帰的にリストします。パラメータを指定しない場合、デフォルトでホームディレクトリになります。

#!/bin/sh

if test $# -eq 0
then
    startdir="$HOME"
else
    startdir="$1"
fi

for f in "$start"/*          # step through all files in the starting directory
do
     echo "$f"               # print the file name
     if test -d "$f"         # is the file a directory? (-d)
     then
        sh "$0" "$f"         # yes call this script with the dir as arg
     fi
done

各ステップについて説明します。

  1. スクリプトにパラメーターが渡されなかった場合は、「$ HOME」を開始ディレクトリーとして使用します。それ以外の場合は、最初のパラメーターを使用します。 ($#には、このスクリプトに渡されるパラメーターの数が含まれており、シェルの組み込みtestコマンドを使用して、それがゼロかどうかを確認します):

    if test $# -eq 0
    then
            startdir="$HOME"
    else
            startdir="$1"
    fi
    
  2. ホームディレクトリのファイルを反復処理します。 "$HOME"/*は、ホームディレクトリの最上位にある非表示でないすべてのファイルとディレクトリに展開されます。

    for f in "$HOME"/*
    do
    
  3. ファイル名を印刷します。知っていると思いますecho

         echo "$f"               # print the file name
    
  4. Shell組み込みのtestコマンドを-dオプションを指定して呼び出します。引数"$f"がディレクトリの場合、testはtrueを返します。ほとんどの場合、簡潔にするために[ -d "$f" ]と書かれていますが、これは実際にはコマンドです。 [sh manページで「test expr」を検索してください]:

        if test -d "$f"         # is the file a directory? (-d)
        then
    
  5. この次のステートメントは、繰り返します。現在実行中のスクリプトの新しいコピーを開始し、現在の「$ f」ディレクトリ名をそれに渡します。 $0は、現在のシェルスクリプトのファイル名に展開されます。ここではファイル名を入力するのではなく、$0を使用しているため、名前が変更されてもこのスクリプトは機能します。たとえば、スクリプトがrlistと呼ばれた場合、sh rlist "$f"と書くこともできますが、スクリプトの名前が変更された場合、存在しないスクリプトが呼び出されるため、スクリプトは正しく機能しなくなります。スクリプト、または間違ったスクリプト。 [sh manページの「特別なパラメータ」を参照してください]:

            sh "$0" "$f"         # yes call this script with the dir as arg
    
  6. ifステートメントとforループを終了します。

         fi
    done
    

ファイルのカウント

これまでのところ、スクリプトはファイルをリストしますが、それらはカウントしません。すべてのファイルとディレクトリの数を取得したい場合は、次のコマンドを実行します。

sh ./scriptname | wc -l

wc -lは「ワードカウント」コマンドであり、-lオプションを指定すると行だけがカウントされます。上記のパイプラインは、ホームディレクトリにあるファイルの数を出力します。

1
RobertL

findを使用すると、再帰せずに現在のディレクトリのディレクトリタイプではありません。

_find . ! -name . -Prune ! -type d | grep -c /
_

...ディレクトリのみの場合は2番目の強打を削除するか、すべてのファイルタイプの場合は_-type_テストを完全に削除します。

再帰がなければファイルごとに1つのパス区切り文字しか表示されないため、何をどこでカウントするかについて混乱がないため、この場合は簡単です。ファイルをカウントする必要があるときに改行をカウントすると、問題が発生する可能性があります。この2つは無関係です。そうでなければ何をすべきか?

_find .//. | grep -c '^\.//\.'
_

...子オブジェクトの正確な数と、現在のディレクトリをルートとするこのオブジェクトを返します。

同様に有効ですが、内部で改行を引用するため逆のロジックを使用し、すべての構成ファイルではなく各ディレクトリをstat()するだけでよいため、おそらくより高速になります。

_\ls -1qRA . | grep -Exc \[^/]+
_

_-R_オプションをlsにドロップすると、再帰せずに機能します。

ただし、ファイル名のマルチバイト文字と互換性のないロケール設定によっては、上記のエラーが誤ったカウントを返す可能性があります。 POSIX準拠のlsの環境に_LC_ALL=C_を配置すると、それを防ぐことができます。かなりのツリーの深さのカウントの場合、そうすることは、結局、パフォーマンスに関する問題にしか役立ちません。

3
mikeserv

find を使用:

非再帰的に言うときは、/ home内のファイル/ディレクトリの数だけが必要で、サブディレクトリは必要ないということですか?その場合は、maxdepthオプションを使用して結果を最上位に制限できます。

find /home -maxdepth 1 | wc -l

使用:

i=0; for home in ~/*; do (( i++ )); done; echo $i

二重括弧と囲まれたi ++の間のスペースに注意してください。

0
Nigel Tufnel