プロジェクト内のコードの行数を数えたいとします。すべてのファイルが同じディレクトリにある場合は、次を実行できます。
cat * | wc -l
ただし、サブディレクトリがある場合、これは機能しません。これが機能するには、cat に再帰モードが必要です。これは xargs の仕事かもしれないと思いますが、もっと洗練された解決策があるのだろうか?
cat
まず、行を数えるために使用する必要はありません。これはUseless Use of Cat (UUoC) と呼ばれるアンチパターンです。現在のディレクトリ内のファイルの行数をカウントするには、次を使用しますwc
。
wc -l *
次に、find
コマンドはサブディレクトリを再帰します。
find . -name "*.c" -exec wc -l {} \;
.
検索を開始するトップディレクトリの名前です
-name "*.c"
興味のあるファイルのパターンです
-exec
実行するコマンドを与える
{}
コマンドに渡される find コマンドの結果です (ここではwc-l
)
\;
コマンドの終了を示します
このコマンドは、見つかったすべてのファイルとその行数のリストを生成します。見つかったすべてのファイルの合計を取得したい場合は、find を使用して (オプションで) ファイルをリストし、-print
xargs を使用してこのリストを引数として渡すことができます。 wc-lへ。
find . -name "*.c" -print | xargs wc -l
Robert Gamble のコメントに対処するための編集 (感謝): ファイル名にスペースまたは改行 (!) が含まれている場合は、 and-print0
の代わりにオプションを使用して、ファイル名のリストがヌル終了文字列と交換されるようにする必要があります。-print
xargs -null
find . -name "*.c" -print0 | xargs -0 wc -l
Unix の哲学は、1 つのことだけを実行し、それをうまく実行するツールを用意することです。
コードゴルフの答えが必要な場合:
grep '' -R . | wc -l
wc -l を単独で使用するだけの問題は、うまく下降できないことです。
find . -exec wc -l {} \;
wc はファイルごとに 1 回実行されるため、合計行数は表示されません (笑!)。
find . -exec wc -l {} +
find がパラメーターの最大 200k 1 , 2 文字の引数制限に達するとすぐに混乱し、代わりに wc を複数回呼び出し、毎回部分的な要約のみを提供します。
さらに、上記の grep トリックは、バイナリ ファイルに遭遇したときに出力に 1 行しか追加されないため、状況によっては有益な場合があります。
コマンド文字を 1 文字追加するだけで、バイナリ ファイルを完全に無視できます。
grep '' -IR . | wc -l
バイナリファイルでも行カウントを実行したい場合
grep '' -aR . | wc -l
制限に関する脚注:
ドキュメントは、文字列サイズの制限なのか、トークンの数の制限なのかについて、少しあいまいです。
cd /usr/include;
find -type f -exec perl -e 'printf qq[%s => %s\n], scalar @ARGV, length join q[ ], @ARGV' {} +
# 4066 => 130974
# 3399 => 130955
# 3155 => 130978
# 2762 => 130991
# 3923 => 130959
# 3642 => 130989
# 4145 => 130993
# 4382 => 130989
# 4406 => 130973
# 4190 => 131000
# 4603 => 130988
# 3060 => 95435
これは、非常に簡単にチャンクすることを意味します。
あなたはおそらく xargs で立ち往生していると思います
find -name '*php' | xargs cat | wc -l
クロマコードの方法でも同じ結果が得られますが、はるかに遅くなります。xargs を使用すると、 cat ing とwc ing は、 findが検索を開始するとすぐに開始できます。
Linuxでの適切な説明: xargs と exec {}
find
デフォルトでディレクトリを再帰するコマンドを使用してみてください。
find . -type f -execdir cat {} \; | wc -l
正しい方法は次のとおりです。
find . -name "*.c" -print0 | xargs -0 cat | wc -l
Unix ファイル名には無効な文字が 2 つしかないため、-print0 を使用する必要があります: null バイトと「/」(スラッシュ)。たとえば、「xxx\npasswd」は有効な名前です。ただし、実際には、名前にスペースが含まれている可能性が高くなります。上記のコマンドは、各単語を個別のファイルとしてカウントします。
検索をファイルに限定するために、-name の代わりに「-type f」を使用することもできます。
Bash を含む比較的最近の GNU ツールを使用できる場合、上記のソリューションで cat または grep を使用するのは無駄です。
wc -l --files0-from=<(find . -name \*.c -print0)
これは、コマンドラインの長さの制限を超えていても、スペース、任意の再帰、任意の数の一致するファイルを含むファイル名を処理します。
wc -cl `find . -name "*.php" -type f`
プロジェクト ディレクトリ内のすべてのファイルに対して、 findとheadを組み合わせて "再帰的な猫"を使用するのが好きです。次に例を示します。
find . -name "*rb" -print0 | xargs -0 head -10000
利点は、head がファイル名とパスを追加することです。
==> ./recipes/default.rb <==
DOWNLOAD_DIR = '/tmp/downloads'
MYSQL_DOWNLOAD_URL = 'http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.10-debian6.0-x86_64.deb'
MYSQL_DOWNLOAD_FILE = "#{DOWNLOAD_DIR}/mysql-5.6.10-debian6.0-x86_64.deb"
package "mysql-server-5.5"
...
==> ./templates/default/my.cnf.erb <==
#
# The MySQL database server configuration file.
#
...
==> ./templates/default/mysql56.sh.erb <==
PATH=/opt/mysql/server-5.6/bin:$PATH
ここにある完全な例については、私のブログ投稿を参照してください。
http://haildata.net/2013/04/using-cat-recursively-with-nicely-formatted-output-include-headers/
「head -10000」を使用したことに注意してください.10,000行を超えるファイルがある場合、明らかに出力が切り捨てられます...ただし、head 100000を使用できますが、「非公式のプロジェクト/ディレクトリブラウジング」の場合、このアプローチは非常にうまく機能します。
各ファイルの行数ではなく、合計行数のみを生成する場合は、次のようにします。
find . -type f -exec wc -l {} \; | awk '{total += $1} END{print total}'
うまく機能します。これにより、スクリプトでさらにテキスト フィルタリングを行う必要がなくなります。
プロジェクト内のコードの行数をカウントする Bash スクリプトを次に示します。ソース ツリーを再帰的にトラバースし、"//" を使用する空白行と単一行コメントを除外します。
# $excluded is a regex for paths to exclude from line counting
excluded="spec\|node_modules\|README\|lib\|docs\|csv\|XLS\|json\|png"
countLines(){
# $total is the total lines of code counted
total=0
# -mindepth exclues the current directory (".")
for file in `find . -mindepth 1 -name "*.*" |grep -v "$excluded"`; do
# First sed: only count lines of code that are not commented with //
# Second sed: don't count blank lines
# $numLines is the lines of code
numLines=`cat $file | sed '/\/\//d' | sed '/^\s*$/d' | wc -l`
total=$(($total + $numLines))
echo " " $numLines $file
done
echo " " $total in total
}
echo Source code files:
countLines
echo Unit tests:
cd spec
countLines
私のプロジェクトの出力は次のようになります。
Source code files:
2 ./buildDocs.sh
24 ./countLines.sh
15 ./css/dashboard.css
53 ./data/un_population/provenance/preprocess.js
19 ./index.html
5 ./server/server.js
2 ./server/startServer.sh
24 ./SpecRunner.html
34 ./src/computeLayout.js
60 ./src/configDiff.js
18 ./src/dashboardMirror.js
37 ./src/dashboardScaffold.js
14 ./src/data.js
68 ./src/dummyVis.js
27 ./src/layout.js
28 ./src/links.js
5 ./src/main.js
52 ./src/processActions.js
86 ./src/timeline.js
73 ./src/udc.js
18 ./src/wire.js
664 in total
Unit tests:
230 ./ComputeLayoutSpec.js
134 ./ConfigDiffSpec.js
134 ./ProcessActionsSpec.js
84 ./UDCSpec.js
149 ./WireSpec.js
731 in total
楽しみ!--カラン