自分のホームディレクトリにあるファイルとディレクトリの総数を計算して表示するスクリプトをどのように作成しますか?

自分のホームディレクトリにあるファイルとディレクトリの総数を計算して表示するスクリプトをどのように作成しますか?

ループを使ってやりたいですfor。これは私が今まで考えたものですが、うまくいきません。

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

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

答え1

forはfind現在のディレクトリのディレクトリタイプではないため、再帰は必要ありません。

find . ! -name . -prune ! -type d | grep -c /

...ディレクトリに対してのみ2番目の爆発を削除するか、-typeすべてのファイル形式のテストを完全に削除してください。

この場合、再帰がないと、ファイルごとに1つのパス区切り文字しか表示されないため、計算する項目と計算する場所に混乱がないため、簡単です。ファイル数を数える必要があるときに改行文字を数えると、問題が発生する可能性があります。 2つのことは互いに関連していません。では、何ができますか?

find .//. | grep -c '^\.//\.'

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

また、動作しますが、反対のロジックを使用します。内部的に改行を引用し、stat()各設定ファイルの代わりに各ディレクトリだけが必要なので、おそらくより速いでしょう。

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

-Rこのオプションを破棄すると、ls再帰なしで動作します。

ただし、上記は、ファイル名のマルチバイト文字と互換性のないロケールによって誤った数を返す可能性があります。LC_ALL=CPOSIX 準拠の環境に配置すると、lsこのようなことは起こらず、かなり大きなツリーの深さの数を使用すると、最終的にはパフォーマンスにのみ役立ちます。

答え2

必要なタスクをほとんど実行できるより高いレベルのコマンドがたくさんありますが、これはシェルスクリプトで同じタスクを実行する方法を示す良い例です。これはうまくいくはずですどのシステムは/bin/sh他のコマンドに依存しません。

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

二つの部分に分けたが、ファイルのリストファイル数の計算。ファイルを再帰的にリストするのは最も複雑ですが、リストがあれば簡単に数えることができます。

ファイルのリスト

このスクリプトは、ホームディレクトリまたは引数として受け取るディレクトリの下のすべてのファイルとディレクトリを繰り返し一覧表示します。パラメータがない場合、デフォルトはホームディレクトリです。

#!/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. optionsを使用してシェル組み込みtestコマンドを呼び出します-dtest引数がディレクトリ"$f"の場合はtrueを返します。これは通常[ -d "$f" ]簡潔に書かれていますが、実際にはコマンドです。 ["test expr"のマニュアルページを検索sh]:

        if test -d "$f"         # is the file a directory? (-d)
        then
    
  5. 次の声明は私たちが繰り返すところです。現在実行中のスクリプトの新しいコピーを開始し、ここに現在の「$ f」ディレクトリ名を渡します。$0現在のシェルスクリプトのファイル名に展開されます。ここにファイル名を入力するのではなく、$0名前が変更されてもスクリプトが機能するようにする方法です。たとえば、スクリプトが呼び出されたときに作成することrlistもできますが、sh rlist "$f"スクリプトの名前が変更された場合は存在しないスクリプトまたは無効なスクリプトを呼び出すため、スクリプトは正しく実行されません。 [マンページの「特殊パラメータ」を参照sh]:

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

         fi
    done
    

ファイル数の計算

これまで、スクリプトはファイルを一覧表示しますが、計算しません。すべてのファイルとディレクトリの数を取得するには、次のコマンドを実行します。

sh ./scriptname | wc -l

wc -l「単語数」コマンドで、-lこのオプションがある行のみを計算します。上記のパイプは、ホームディレクトリのファイル数である数字を印刷します。

答え3

使用探す:

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

find /home -maxdepth 1 | wc -l

使用:

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

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

関連情報