ls -l *の違い| wc -lとls -l ||トイレ-l

ls -l *の違い| wc -lとls -l ||トイレ-l

膨大な量のファイルのリストを含むフォルダがありますが、その数を数えたいです。私はこれをやっていて、ls -l *.json | wc -lコマンドが機能しなくなるほどリストが十分に大きくなるまでうまくいきました。

後で一度試してみましたが、ls -l | grep .json | wc -l本当にうまくいきました。

それでは、2つの違いが何であるかを知りたいです。後者はlsすべてのファイルを一度に処理せずに継続的にストリーミングしてgrepからwc?そうですか、それとも別の方法で動作しますか?

答え1

.json現在のディレクトリ内の拡張子を持つ隠しファイルの数を数えるには、次のようにします。

(){echo $#} *.json(NoN)

Nの場合、nullglobここではoN不要なソートを無効にします)。

ls -l | grep .json | wc -lこれは、次のようなさまざまな理由で間違っています。

  • .単一文字に一致する正規表現演算子です。または文字列を検索したい場合.jsongrep -F .jsongrep '\.json'grep '[.]json'
  • これはXjson各行で検索されます。を使用すると、ls -lファイル名、ユーザー名、グループ名、シンボリックリンクの宛先などを含めることができる印刷できますXjson
  • ファイル名には、0とof /(リンク先に含めることができます/)を除くすべてのバイト値を含めることができます。したがって、名前がxjson\nyjsonシンボリックリンクのファイルがある場合、ファイルはすべて3行を印刷します。一部のファイル名に現在のロケールバイトシーケンスで有効な文字を形成しないajson\nbjson文字が含まれている場合は、驚くことがあります。-qls -lXjson
  • grep | wc -l一般的に置き換えることができますgrep -c

ls -l *.json | wc -lもっと悪い。横に引数リストが長すぎると、潜在的な問題が発生する可能性があります。@L.ScottJohnsonも次のように指摘しました。

  • 隠されていないファイルがないと、globを一致させることができないため、エラーが.json発生します。0zsh*.json
  • 各パラメータタイプについて目次ls -lその内容がリストされているため、ディレクトリがある場合は、そのリストのすべてのdir.json行が計算されます。通常、-dglob拡張をに渡すときにaを使用しようとしていますls
  • .jsonファイル名がで始まる場合、-そのファイル名はオプションとして扱われます(特にオプションではなく、引数の後でもオプションを受け入れるlsGNUまたはビジボックスの実装)。ls
  • 上記のように、ファイル名またはシンボリックリンク先に改行文字が含まれていると問題が発生します。

次の方法を使用してほとんどの問題を解決できます。

LC_ALL=C ls -qd -- *.json | wc -l

ただし、実際の操作はすべてシェルで行われます。 shellは、*.jsonファイルのリストと一致してに渡す拡張ですlsls入力のために、各ファイルを別々の行に印刷してwc計算できます。また、存在するかどうかを確認するためにそれぞれにシステムコールを実行するなどの不要lsな操作がたくさんあります(ユーザー/グループ名解決のためにaといくつかのuid / gidを実行し、シンボリックリンクにsを使用します)。 (シェルはすでに拡張子をソートしています)。stat()-llstat()readlink()*.json

シェルはこの拡張を独自にうまく計算します。

の場合は(){echo $#} *.json(NoN)匿名関数を使用し、一時配列を使用することもできますfiles=(*.json(NoN)); echo $#files

また読むlsリストを作成するには現在のディレクトリの内容を使用するため、以前と同じように各ファイルを個別に見つける必要はありません。

この構文は具体的ですzsh。 POSIXの対応する構文はsh次のようになります。

set -- [*].json *.json
case $1$2 in
  ('[*].json*.json') shift 2;;
  (*) shift;;
esac
echo "$#"

(ファイルリストは"$@"(ソート)にあります。)

答え2

拡張ファイルリストが長すぎると、ファイルリストを拡張するためにシェルを使用するため、元のコマンドが失敗する可能性があります。

ls -l | grep .json | wc -l 

問題ありません。コマンドラインは短く(拡張なし)、grepは1行ずつフィルタリングするためです。

ドットはドットだけでなく、すべての文字と一致します。固定文字列には -F を使用します。

ls -l | grep -F .json | wc -l 

xjsonこれにより、誤ってファイルを一致させたり、そのような愚かなことが発生したりしません。

コマンドに関するいくつかの注意事項と意図した目標を達成するための他の(より強力な)方法がまだありますが、これらの問題に加えて、ファイル名ワイルドカード(シェル拡張子など)でフィルタリングすることとパイプという2つのコマンドの違いがあります。 -to-grep

関連情報