すべてのサブディレクトリのファイル数を報告する方法は?

すべてのサブディレクトリのファイル数を報告する方法は?

すべてのサブディレクトリを確認し、含まれるファイル数を報告する必要があります(追加の再帰なし)。

directoryName1 numberOfFiles
directoryName2 numberOfFiles

答え1

これは安全で持ち運び可能な方法で行われます。奇妙なファイル名のために混乱しません。

for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \; | wc -l && echo $f; done

まずファイル番号を印刷してから、ディレクトリ名を別の行に印刷します。 OPの形式を維持するには、追加の形式を指定する必要があります。

for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \;|wc -l|tr '\n' ' ' && echo $f; done|awk '{print $2"\t"$1}'

興味のある特定のサブディレクトリセットがある場合は、*それをそのサブディレクトリに置き換えることができます。

なぜそんなに安全ですか?(したがって台本にふさわしい)

ファイル名に 。以外の文字を含めることができます/。シェルやコマンドで特別に扱われる文字があります。これにはスペース、改行、ダッシュが含まれます。

このfor f in *構造を使用することは、含まれている内容に関係なくすべてのファイル名を取得する安全な方法です。

ファイル名を変数に入れた後に提供したばかりのオプションを含めると、.filenameがエラーを引き起こすのと同じ問題を回避する必要がありますfind $f。これを避ける方法は、名前の前に使用することです。これは同じ意味を持ちますが、ダッシュで始まらなくなります。$f-testfind./

改行とスペースも問題です。$fファイル名に "hello, buddy" が含まれている場合find ./$f、はいfind ./hello, buddy。存在しないと文句を言い、絶対に見つかりません。これは避けやすいです。変数の周りに引用符を使用します。find./hello,buddy./hello, buddy

最後に、ファイル名に改行を含めることができるため、ファイル名のリストから改行を計算することは効果がありません。改行がある各ファイル名の追加数が得られます。これを回避するには、ファイルリストから改行を数えるのではなく、個々のファイルを表す改行(またはその他の文字)を数えます。これがfindコマンドにsimple-exec echo \;とnotがある理由です-exec echo {} \;。統計ファイルに新しい行を印刷したいです。

答え2

「再帰なし」とは、サブdirectoryName1ディレクトリが存在する場合にサブディレクトリのファイル数を数えないことを意味します。その場合、指定されたディレクトリにあるすべての一般ファイルの数を数える方法は次のとおりです。

count=0
for d in directoryName1 directoryName2; do
  for f in "$d"/* "$d"/.[!.]* "$d"/..?*; do
    if [ -f "$f" ]; then count=$((count+1)); fi
  done
done

この-fテストは2つの機能を実行します。上記のglobのいずれかに一致するものが通常のファイルかどうかをテストし、項目が一致するかどうかをテストします(globの1つが何も一致しない場合、パターンは1のままです)。 。タイプに関係なく、特定のディレクトリ内のすべてのエントリ数を計算するには、-fに置き換えます-e

Kshには、パターンをドットファイルに一致させ、パターンに一致するファイルがない場合は空のリストを生成する方法があります。したがって、ksh では次のような一般的なファイルを計算できます。

FIGNORE='.?(.)'
count=0
for x in ~(N)directoryName1/* ~(N)directoryName2/*; do
  if [ -f "$x" ]; then ((++count)); fi
done

または次のすべてのファイル:

FIGNORE='.?(.)'
files=(~(N)directoryName1/* ~(N)directoryName2/*)
count=${#files}

Bashには、このプロセスを簡素化するさまざまな方法があります。一般的なファイル数を数えるには:

shopt -s dotglob nullglob
count=0
for x in directoryName1/* directoryName2/*; do
  if [ -f "$x" ]; then ((++count)); fi
done

すべてのファイル数を計算します。

shopt -s dotglob nullglob
files=(directoryName1/* directoryName2/*)
count=${#files}

いつものように、zshでははるかに簡単です。一般的なファイル数を数えるには:

files=({directoryName1,directoryName2}/*(DN.))
count=$#files

すべてのファイルを計算する(DN.)ように変更します。(DN)

1各パターンはそれ自体が一致します。そうしないと、結果が間違っている可能性があります(たとえば、数字で始まるファイルの数を数えると、名前がファイルである可能性があるため、そうすることはできません)。for x in [0-9]*; do if [ -f "$x" ]; then …[0-9]foo

答え3

標準のLinuxソリューションを探していると仮定すると、これを達成するための比較的簡単な方法は次のとおりですfind

find dir1/ dir2/ -maxdepth 1 -type f | wc -l

ここでは、1findに設定された2つの指定されたサブディレクトリを巡回します-maxdepth。これは追加の再帰を防ぎ、改行-type f()で区切られたファイルのみを報告します。次に、結果をパイプで連結してwcその行数を計算します。

答え4

findこれは、、、echoおよびlsを使用して結果を取得する「無差別」方法ですwcxargsawk

find . -maxdepth 1 -type d -exec sh -c "echo '{}'; ls -1 '{}' | wc -l" \; | xargs -n 2 | awk '{print $1" "$2}'

関連情報