膨大な量のファイルのリストを含むフォルダがありますが、その数を数えたいです。私はこれをやっていて、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
これは、次のようなさまざまな理由で間違っています。
.
単一文字に一致する正規表現演算子です。または文字列を検索したい場合.json
。grep -F .json
grep '\.json'
grep '[.]json'
- これは
Xjson
各行で検索されます。を使用すると、ls -l
ファイル名、ユーザー名、グループ名、シンボリックリンクの宛先などを含めることができる印刷できますXjson
。 - ファイル名には、0とof
/
(リンク先に含めることができます/
)を除くすべてのバイト値を含めることができます。したがって、名前がxjson\nyjson
シンボリックリンクのファイルがある場合、ファイルはすべて3行を印刷します。一部のファイル名に現在のロケールバイトシーケンスで有効な文字を形成しないajson\nbjson
文字が含まれている場合は、驚くことがあります。-q
ls -l
Xjson
grep | wc -l
一般的に置き換えることができますgrep -c
。
ls -l *.json | wc -l
もっと悪い。横に引数リストが長すぎると、潜在的な問題が発生する可能性があります。@L.ScottJohnsonも次のように指摘しました。
- 隠されていないファイルがないと、globを一致させることができないため、エラーが
.json
発生します。0
zsh
*.json
- 各パラメータタイプについて目次、
ls -l
その内容がリストされているため、ディレクトリがある場合は、そのリストのすべてのdir.json
行が計算されます。通常、-d
glob拡張をに渡すときにaを使用しようとしていますls
。 .json
ファイル名がで始まる場合、-
そのファイル名はオプションとして扱われます(特にオプションではなく、引数の後でもオプションを受け入れるls
GNUまたはビジボックスの実装)。ls
- 上記のように、ファイル名またはシンボリックリンク先に改行文字が含まれていると問題が発生します。
次の方法を使用してほとんどの問題を解決できます。
LC_ALL=C ls -qd -- *.json | wc -l
ただし、実際の操作はすべてシェルで行われます。 shellは、*.json
ファイルのリストと一致してに渡す拡張ですls
。ls
入力のために、各ファイルを別々の行に印刷してwc
計算できます。また、存在するかどうかを確認するためにそれぞれにシステムコールを実行するなどの不要ls
な操作がたくさんあります(ユーザー/グループ名解決のためにaといくつかのuid / gidを実行し、シンボリックリンクにsを使用します)。 (シェルはすでに拡張子をソートしています)。stat()
-l
lstat()
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