web-dev-qa-db-ja.com

シェルスクリプトを使用してファイルとディレクトリをカウントする

私はbashスクリプトを学習しており、引数として指定されたディレクトリ内のファイルとディレクトリをカウントするスクリプトを作成しました。私は奇妙に思える1つの方法でそれを動作させており、それを行うより簡単な方法があるかどうか疑問に思っています。

動作するコードをコメントアウトしましたが、比較のために残しておきます。代わりにfor- loopを機能させようとしていますが、代わりにifステートメントを使用して、指定された場所のアイテムがファイルかディレクトリかを検出しています。

編集:コメントされたコードは、指定された場所のサブディレクトリ内のすべてのファイルとディレクトリもカウントすることがわかりました!これを防ぎ、特定の場所のファイルとディレクトリを数えるだけの方法はありますか?

#!/bin/bash

LOCATION=$1
FILECOUNT=0
DIRCOUNT=0

if [ "$#" -lt "1" ]
then
    echo "Usage: ./test2.sh <directory>"
    exit 0
fi

#DIRS=$(find $LOCATION -type d)
#FILES=$(find $LOCATION -type f)

#for d in $DIRS
#do
#   DIRCOUNT=$[$DIRCOUNT+1]
#done

#for f in $FILES
#do
#   FILECOUNT=$[$FILECOUNT+1]
#done

for item in $LOCATION
do
if [ -f "$item" ]
    then
         FILECOUNT=$[$FILECOUNT+1]
    Elif [ -d "$item" ]
        then
         DIRCOUNT=$[$DIRCOUNT+1]
fi
done

echo "File count: " $FILECOUNT
echo "Directory count: " $DIRCOUNT

何らかの理由で、for- loopの出力は、場所をどこに指定しても、常に返されます。

File count: 0 , Directory count: 1
14
Alan Smith

指定されたディレクトリ内のファイルのリストを繰り返し処理していません。 /*の後に$LOCATIONを追加します。スクリプトは次のようになります。

...
for item in $LOCATION/*
do
...

Dogbaneが指摘したように、/*を追加するだけで、.で始まらないファイルのみがカウントされます。そのためには、次のことを行う必要があります。

...
for item in $LOCATION/* $LOCATION/.*
do
...
5
Rubens

以下に示すようにfindを使用します。このソリューションは、スペース、改行、ドットファイルを含むファイル名を正しくカウントします。

FILECOUNT="$(find . -type f -maxdepth 1 -printf x | wc -c)"
DIRCOUNT="$(find . -type d -maxdepth 1 -printf x | wc -c)"

DIRCOUNTには現在のディレクトリ(.)。これが望ましくない場合は、1を引きます。

((DIRCOUNT--)) # to exclude the current directory
14
dogbane

問題を解決するために使用できます:

_FILECOUNT=$(find $LOCATION -type f | wc -l)
DIRCOUNT=$(find $LOCATION -type d | wc -l)
_

findは、すべてのファイル(_-type f_)またはディレクトリ(_-type d_)を_$LOCATION_の下で再帰的に検索します。 _wc -l_は、それぞれの場合にstdoutに書き込まれた行数をカウントします。

ただし、学習したい場合は、bashスクリプトの方が適している場合があります。コメント:

  • _$LOCATION_のみでファイル/ディレクトリを検索する場合(サブディレクトリなどの下で再帰的ではない)、_for item in $LOCATION/*_を使用できます。ここで、_*_はファイル/ディレクトリのリストに展開されます。 _$LOCATION_ディレクトリ内。欠落している_*_が、元のスクリプトが0/1を返す理由です(_$LOCATION_ディレクトリ自体がカウントされる唯一のアイテムであるため)。
  • 最初に、_$LOCATION_が実際に_[ -d $LOCATION ]_を持つディレクトリであることを確認することをお勧めします。
  • 算術式には、$(( ... ))を使用します(例:FILECOUNT=$(( FILECOUNT + 1 )))。
  • すべてのファイル/ディレクトリを再帰的に検索する場合は、findをループと組み合わせることができます。

例:

_find $LOCATION | while read item; do
    # use $item here...
done
_
12

... am wondering if there is a simpler way of doing it.

あなたがそう言うなら;)

または、スクリプトを

find /path/to/directory | wc -l

現在のディレクトリの場合:

find . | wc -l
2
sampson-chen

使用する

find $LOCATION -maxdepth 1 -type f | wc -l

ファイルの数、および

find $LOCATION -maxdepth 1 -type d | wc -l

ディレクトリのカウント用

2
beny23