/bin/cat: パラメーターのリストが長すぎます。

/bin/cat: パラメーターのリストが長すぎます。

私のフォルダには119766個のファイルがあります。 CSVファイルです。すべてのファイルの総行数を見つけたいと思います。

次のコマンドを実行しようとしています。

cat * |wc -l

ただし、次のエラーが発生します。

-bash: /bin/cat: パラメーターのリストが長すぎます。

どうすればいいですか?この問題を解決する方法はありますか?

1つ追加したいのは、行全体の数が非常に大きくなることです。

答え1

さて、この質問に新しい根拠を提供するには、cat次のようにする必要があります。

find . -type f -exec cat {} + | wc -l

許可されているファイル名の最大数を使用してa()を続行し、catすべてを 。+wc-maxdepth 1

代わりに、--files0-fromGNUオプションを使用できます。wc

find . -type f -print0 | wc -l --files0-from=- | tail -1

このオプションを使用すると、wc内容を読むのではなくファイル名標準入力ではヌル文字で区切られます。を使用すると、-print0これらのfindファイル名はヌルバイトで区切られて印刷されます。各ファイルの行数は印刷され続けるため、最後wcの要約行を除くすべての行をスキップすることをお勧めしますtail

どちらのソリューションもすべてのロケールで動作するという利点がありますが、@casのソリューションは調整する必要があります(たとえば、「total」はドイツ語で「insgesamt」です)。

答え2

各個々のファイルの行数が必要な場合:

find . -type f -exec wc -l {} + | awk '! /^[ 0-9]+[[:space:]]+total$/'

そのうちのいくつかはあまりにも多くのファイルを処理しているので、行の総数を除外しました。単一のコマンドラインにできるだけ多くのファイル名を入れようとしますが、find ... -exec ... +これは119,766個のファイルよりはるかに少なくなりますwc。独自の結果別々の「マスター」ライン。

すべてのファイルの合計行数をマージするには、次のいずれかの方法を使用します。

find . -type f -exec wc -l {} + | 
    awk '/^[ 0-9]+[[:space:]]+total$/ {print $1}' | 
    xargs | sed -e 's/ /+/g' | bc

これは単に総行数の行数を印刷し、パイプを使用して行のすべての数をxargs取得し、sedを使用してスペースを+符号に変換し、大量のデータをパイプしてbc計算を実行します。

出力例:

$ cd /usr/share/doc
$ find . -type f -exec wc -l {} + | 
    awk '/^[ 0-9]+[[:space:]]+total$/ {print $1}' | 
    xargs | sed -e 's/ /+/g' | bc 
53358931

更新 2022-05-05

wc -l実行するのが最善ですsh。これにより、ファイル名を呼び出すときに問題が発生するリスクを防ぎます。total総行が出力の最後の行である以外に、wc「total」というファイルの出力と実際の総行を区別する方法はありません。したがって、「total」という単純なawkスクリプトは安定して動作しません。

個々のファイルの数を表示するには(すべて除く):

find . -type f -exec sh -c 'wc -l "$@" | sed "\$d"' sh {} +

これはwc -lすべてのファイル名に対して実行され、各バッチ実行から最後の行(「完全」行)を削除します-exec

sedスクリプトでは、$dスクリプトはより一般的な一重引用符文字列ではなく二重引用符文字列にあるため、エスケープする必要があります。文字sh -c列全体が一重引用符であるため、二重引用符が使用されます。一重引用符の中に一重引用符を挿入する$よりも、シンボルをエスケープする方が簡単で読みやすいです。'\''

合計のみ表示:

find . -type f -exec sh -c 'wc -l "$@" | awk "END {print \$1}"' sh {} + |
  xargs | sed -e 's/ /+/g' | bc

sedbyを介して渡された各ファイルバッチの最後の行を削除するのではなく、各バッチの最後の行(「すべて」)のみを印刷します。その後の出力は、各数字の間に文字を含む単一行(xargs)に変換され(sedは空白を+に変換する)、計算を実行するためにパイプされます。wcshfind ... -execawkfind+bc

$dsedスクリプトのスクリプトと同様に、$1awkスクリプトのスクリプトも二重引用符でエスケープする必要があります。

答え3

ファイルが多すぎると、情報を標準出力に送信したくない可能性があるため、次のことができます。

IFS="\n"; for file in find ./ -type f; do wc -l "$file" >> ~/linecount.txt; done

関連情報