user4556274はすでにその理由に答えています。私の答えは、ファイルを適切にカウントする方法に関する追加情報を提供することだけです。
Unixコミュニティでls
は、ファイル名に制御文字または隠し文字が含まれている可能性があるため、出力の解析は非常に悪い考えであるという一般的なコンセンサスがあります。たとえば、ファイル名に改行文字があるls | wc -l
ため、出力には5行あることがわかりますがls
(実際には)、ディレクトリには4つのファイルしかありません。
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
方法#1:ユーティリティの検索
このfind
コマンドは通常、ファイル名の解析に使用されますが、ここではiノード番号を出力することで役立ちます。ディレクトリでもファイルでも、一意のiノード番号は1つだけです。したがって、via を使用-printf "%i\n"
して除外すると、ファイルの正確なカウントを取得できます。(サブディレクトリへの再帰的な下降を防ぐための使用に注意してください).
-not -name "."
-maxdepth 1
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
方法#2:globstar
シンプル、迅速、そしてほとんどポータブルな方法:
$ set -- *
$ echo $#
228
set
コマンドは、シェルの位置パラメーター(のような$<INTEGER>
変数echo $1
)を設定するために使用されます。これは/bin/sh
、配列不足の制限を回避するためによく使用されます。追加のチェックを実行するバージョンは、Unix&LinuxのGilleの回答に記載されています。
などの配列をサポートするシェルではbash
、次を使用できます。
items=( dir/* )
echo ${#items[@]}
スチールドライバーがコメントで提案した通り。
globstar find
を使用した方法と同様のトリックをwc
使用してstat
、行ごとにiノード数をカウントできます。
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
別のアプローチは、for
ループでワイルドカードを使用することです。(このテストは別のディレクトリを使用して、このアプローチがサブディレクトリに下降するかどうかをテストしますが、そうではありません-16はmyの検証済みアイテム数です~/bin
)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
方法#3:他の言語/通訳
Pythonはまた、os.listdir()
関数(非再帰的であり、引数として指定されたディレクトリ内の項目のみをリストします)を指定してリストの長さを出力することにより、問題のあるファイル名を処理できます。
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
こちらもご覧ください
ls | wc -l
ファイル名に改行があるファイルがあると失敗します。これはより回復力がありますfind . -mindepth 1 -maxdepth 1 -printf . | wc -c