ls
私のタスクは、コマンドを使用せずに現在のディレクトリ内のファイルの数を印刷することでしたwc
。
スクリプトに次の行を入力しました。
#!/bin/bash
find . -maxdepth 1 -type f \( ! -iname ".*" \) > list3
grep .* -c list3 > /dev/tty
出力は次のようになります。
..:0
.6.1c.sh.swp:1
list3:22
私の理解によれば、それは次のようになるはずです:22
なぜそれが機能しないのですか?
答え1
なぜgrep
正しく動作しないのか
それが実際に探しているパターンであるgrep
ことを伝える必要があるため、これは機能しません。.*
grep '.*' -c list3
シングルクォートを使用しない場合、シェルは.*
ディレクトリ内のすべてのファイル名を展開します。これはファイル名の拡張たとえばa.txt b.txt
、次のgrep
ようになります。
grep a.txt b.txt -c list3
以来一重引用符拡大を防ぐには、これが最善の方法です。
コマンドが間違っている箇所grep
:
ところで、ここでのパターンは間違った方向に進んでいます。.
正規表現のピリオドはどれでも文字であり、ドットそのものではない。ページman
詳細については、正規表現を参照してください。つまり、現在の正規表現は、「任意の文字を検索し、次に任意の文字のシーケンスを検索」するということです。かなり冗長です。
実際に一致させるつもりなら:
[ドット] [その他]
…ドットをエスケープする必要があります:
\.*
find
コマンドを改善できる箇所:
何を取り除こうとしているのか分からない
\( ! -iname ".*" \)
コマンドfind
は、現在の作業ディレクトリのドットをすべてのファイルの先頭に付加するため、ここでは何も削除されません。次のように実行することもできます。
find . -maxdepth 1 -type f
答え2
元の問題を解決するには、ls
とのないファイルをカウントしますwc
。
純粋なシェル構文:
files=0
for i in *; do
[ -f "${i}" ] && files=$((files+1))
done
echo ${files}
隠しファイルをカウントに追加するには、for
ループの前にグロブ設定を変更するだけです。
あるいは、find
シェル拡張を楽しんでください:
echo $(($(find -maxdepth 1 -type f -printf '+1')))