for
ループでそれを実行したいと思います。これは私がこれまでに思いついたもので、機能しません。
for home in /home/ {.,/}*; do echo "$home"; done
可能であれば、これを非再帰的に行いたいと思います。
やりたいことをほぼ実行する上位レベルのコマンドは多数ありますが、これはシェルスクリプトで同じことを行う方法の優れたデモです。これは、/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
各ステップについて説明します。
スクリプトにパラメーターが渡されなかった場合は、「$ HOME」を開始ディレクトリーとして使用します。それ以外の場合は、最初のパラメーターを使用します。 ($#には、このスクリプトに渡されるパラメーターの数が含まれており、シェルの組み込みtest
コマンドを使用して、それがゼロかどうかを確認します):
if test $# -eq 0
then
startdir="$HOME"
else
startdir="$1"
fi
ホームディレクトリのファイルを反復処理します。 "$HOME"/*
は、ホームディレクトリの最上位にある非表示でないすべてのファイルとディレクトリに展開されます。
for f in "$HOME"/*
do
ファイル名を印刷します。知っていると思いますecho
:
echo "$f" # print the file name
Shell組み込みのtest
コマンドを-d
オプションを指定して呼び出します。引数"$f"
がディレクトリの場合、test
はtrueを返します。ほとんどの場合、簡潔にするために[ -d "$f" ]
と書かれていますが、これは実際にはコマンドです。 [sh
manページで「test expr」を検索してください]:
if test -d "$f" # is the file a directory? (-d)
then
この次のステートメントは、繰り返します。現在実行中のスクリプトの新しいコピーを開始し、現在の「$ f」ディレクトリ名をそれに渡します。 $0
は、現在のシェルスクリプトのファイル名に展開されます。ここではファイル名を入力するのではなく、$0
を使用しているため、名前が変更されてもこのスクリプトは機能します。たとえば、スクリプトがrlist
と呼ばれた場合、sh rlist "$f"
と書くこともできますが、スクリプトの名前が変更された場合、存在しないスクリプトが呼び出されるため、スクリプトは正しく機能しなくなります。スクリプト、または間違ったスクリプト。 [sh
manページの「特別なパラメータ」を参照してください]:
sh "$0" "$f" # yes call this script with the dir as arg
if
ステートメントとfor
ループを終了します。
fi
done
ファイルのカウント
これまでのところ、スクリプトはファイルをリストしますが、それらはカウントしません。すべてのファイルとディレクトリの数を取得したい場合は、次のコマンドを実行します。
sh ./scriptname | wc -l
wc -l
は「ワードカウント」コマンドであり、-l
オプションを指定すると行だけがカウントされます。上記のパイプラインは、ホームディレクトリにあるファイルの数を出力します。
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
_を配置すると、それを防ぐことができます。かなりのツリーの深さのカウントの場合、そうすることは、結局、パフォーマンスに関する問題にしか役立ちません。
find を使用:
非再帰的に言うときは、/ home内のファイル/ディレクトリの数だけが必要で、サブディレクトリは必要ないということですか?その場合は、maxdepth
オプションを使用して結果を最上位に制限できます。
find /home -maxdepth 1 | wc -l
使用:
i=0; for home in ~/*; do (( i++ )); done; echo $i
二重括弧と囲まれたi ++の間のスペースに注意してください。