LoCでファイルディレクトリを並べ替えようとしています。
しかし、sort
ラインをパイプで接続すると何もしないようです。
paths=`find ./src/ | egrep "\.(cpp|h)$"`
for path in $paths; do
wc -l $path | sort -n;
done
結果は次のとおりです(予約注文でソートされますが、find
数字wc
は無視されます)。
50 /a/a.cpp
10 /a/a.h
200 /b/b.cpp
13 /b/b.h
...
パイプの代わりにファイルにソートを使用する場合:
for path in $paths; do
wc -l $path >> test.txt;
done
sort -n test.txt
それする働く:
```bash
10 /a/a.h
13 /b/b.h
50 /a/a.cpp
200 /b/b.cpp
...
パイプラインバージョンが機能しないのはなぜですか?
答え1
それぞれwc
の出力を個別に、にsort
パイプします。ループの出力全体を処理するためにパイプを移動すると、次のように動作します。
paths=`find ./src/ | egrep "\.(cpp|h)$"`
for path in $paths; do
wc -l $path
done | sort -n
find
出力を繰り返さないでください。;また、フィルタリングされた出力egrep
に使用する必要はありません。find
以下を使用して上記のすべてのタスクを処理できます。
find ./src/ \( -name '*.cpp' -o -name '*.h' \) -exec wc -l {} \; | sort -n
または「全体」行があっても大丈夫ならより効率的に、
find ./src/ \( -name '*.cpp' -o -name '*.h' \) -exec wc -l {} + | sort -n
(ファイル名に改行文字が含まれていると、まだうまくいきません。)
答え2
最初のループは、wc -l
各ループの単一ライン出力を個別に整列し、順番に出力します。動作しません(予想される結果です!)。
2番目のアプローチは、最初にwc
すべての通話のすべての回線を集計してからソートします。これが正しいアプローチです。途中にファイルがあるかどうかはここでは問題ではありません。問題は、最初のループで実際に何もソートしないことです。
だから、
( for path in $paths; do
wc -l $path
done ) | sort -n
動作する必要があります。
find
呼び出しはegrepを使用して出力をフィルタリングするため、奇妙です(たとえば、CMakeビルドで時々見つけることができるように、.cppで終わるフォルダと同じように興味深い結果につながります)。find -type f '(' -iname '*.cpp' -o -iname '*.h' ')'
しかし、私はお勧めしません。find
空白(非常に一般的です)、改行文字などを含むファイル名は、何らかの理由ですべて壊れる可能性があるため、ここですべて一緒に使用します。
代わりに、シェル(私の推測ではbash)が直接提供するものを使用してください。
shopt -s nullglob ## don't fail on empty globs
shopt -s globstar
for path in **/**.{h,cpp} ; do
wc -l "${path}"
done | sort -n
実際に短くすることもできます。
shopt -s nullglob ## don't fail on empty globs
shopt -s globstar
wc -l **/*.{h,cpp} | sort -n
答え3
find
wc
そしてユーティリティのGNU実装は、head
ファイルパスに改行文字が含まれていないと仮定します。
{
find . '(' -name '*.h' -o -name '*.cpp' ')' -print0
printf '%s\0' /dev/null
} |
wc -l --files0-from=- |
head -n -2 | # remove up to 2 trailing lines to remove the /dev/null
# and possibly "total" lines
sort -n
-exec wc -l {} +
「全体」行のみが出力されることを保証するこの方法とは対照的です。
複数のファイルが渡されると、1行だけ出力される問題がまだありますwc
。total
ここでは、追加のコンテンツを追加し/dev/null
て最後に削除してこの問題を解決します。