はじめに結論ですが、
grep -rI '' foo|wc -l
がいいと思います。
次のようなスクリプトで作られるディレクトリで試しましょう。Ubuntuのshのecho
やBSD echo(Macの/bin/echo
)ではなく、bashのecho
を使ってください。
#!/bin/bash rm -r foo rm b mkdir -p foo/bar mkdir -p foo/.baz echo -n 1 > foo/a echo 2 > 'foo/b b' echo 3 > foo/.c echo -e '456\n\n\n\n8' > foo/bar/d echo 9 > foo/.baz/e echo -en '\x00' > foo/f echo -en '\x00' > foo/g echo -en '\x00' > foo/h echo -en '\x00' > foo/i
上のスクリプトで作られるディレクトリfoo
には、テキストファイルが5つあり、行数の合計は9(空行を無視すると6)になります。
ディレクトリ内のテキストファイルの総行数を求める方法をネットで探すといろんな説が見つかりますが、一つずつ試してみましょう。(参考:ファイルの行数を数えるのは「wc -l file」ではありません)
find foo -type f | xargs wc -l
結果は7(間違い。ファイル名に空白が含まれる場合に未対応)
find foo -type f -print0 | xargs -0 wc -l
結果は8(間違い。ファイルの末尾が改行でないいときに未対応)
find foo -type f -print0 | xargs -0 awk 'END{print NR}'
結果は13(間違い。バイナリファイルの処理が不適切)
grep -r . foo | wc -l
結果は10(間違い。バイナリファイルの処理が不適切)
grep -rI . foo | wc -l
結果は6(間違い。空行を無視するならこれでよい)
grep -rI '' foo | wc -l
結果は9(正解)
shopt -s dotglob; grep -rI '' foo/* | wc -l; shopt -u dotglob
結果は9(bash限定だが正解)
おまけ:特定のディレクトリを除外したいとき
mkdir -p foo/foo/.baz echo 10 > foo/foo/.baz/10 mkdir foo/abaz echo 11 > foo/abaz/11
.baz
という名前のディレクトリをすべて除外したいときは、
grep -rI '' foo | grep -v '/\.baz/' | wc -l
比較的新しいgrepなら次のようにも書けます。
grep -rI '' --exclude-dir='\.baz' foo | wc -l
ディレクトリfoo/.baz
だけを除外して、foo/foo/.baz
は除外しないときは、
grep -rI '' foo | grep -v '^foo/\.baz/' | wc -l