forループでは変数は増加しません。

forループでは変数は増加しません。

作業ディレクトリのディレクトリ数を印刷しようとしています。何らかの理由で私のカウンターは増加しません。なんだか教えてください?

#!/bin/bash
n=0
for afile in $(ls)
do
    if [ -d $afile ]
    then
      (( n ++ ))
    fi
done
echo There are $n directories under the current directory $(pwd).
exit 0

奇妙なことに、このプログラムはls..(upディレクトリ)を通して繰り返されるようです。

for myfile in $(ls ..)
do
    if [ -d "../$myfile" ]
    then
      echo "../$myfile (dir)"
    else
      echo ../$myfile
    fi
done
exit 0

答え1

(現在のディレクトリから)非表示のディレクトリの数を数えるには、次のようにしますbash

shopt -s nullglob
set -- */
printf 'There are %d non-hidden subdirectories in %s\n' "$#" "$PWD"

隠しディレクトリの数を含めるには:

shopt -s dotglob nullglob
set -- */
printf 'There are %d subdirectories in %s\n' "$#" "$PWD"

このコードの目的は、スキーマを拡張し、*/スキーマが拡張された後に名前の数を数えることです。このパターンはスラッシュで終わるのでただディレクトリ名(またはディレクトリへのシンボリックリンク名)に展開されます。

ディレクトリ名は位置引数などに割り当てられ、$1これらの引数の数はシェルによって保持されます(したがって、計算するために実際にループを回す必要はありません)。$2set$#

bash配列がより快適であると思われる場合は、次のようにします。

shopt -s dotglob nullglob
dirs=( */ )
printf 'There are %d subdirectories in %s\n' "${#dirs[@]}" "$PWD"

これは、位置パラメータの代わりに名前付き配列を使用することを除いて、本質的に同じです。

dotglobのシェルオプションは、隠された名前と隠されていない名前のbash両方と一致します。*シェルnullglobオプションを使用すると、一致しないパターンは何も拡張されません。

関連:

答え2

あなたのコードは私にはうまくいきますが、いくつかのバグがあり、場合によっては失敗します(たとえば、ファイル名にスペースが含まれている場合など)。

  • まずはしないでください。lsを解析する。代わりに繰り返しのためにglobを使用してください。つまり、$(ls)*
  • 変数を読み取るときは、引用符で囲む必要があります。つまり、"$foo"代わりにを使用してください$foo。引用しないと、シェルは出力を空白などのIFSに分割します。スクリプトを使用してこれをテストできます。スペースなしでいくつかのディレクトリを含め、スペースでテストします。電子のみが計算されます。

固定コードは次のとおりです。

#!/bin/bash
n=0
for afile in *
do
    if [ -d "$afile" ]
    then
      (( n ++ ))
    fi
done
echo There are $n directories under the current directory $(pwd).
exit 0

これが明らかであるかどうかはわかりませんが、スクリプトは現在のディレクトリで実行されます。

関連情報