dotglobの現在の値を使用します。

dotglobの現在の値を使用します。

私はbashプロンプトPS1で作業しており、現在のディレクトリのファイル数を印刷したいと思います。

動作するコードを書いたが、
この(冗長)スクリプトを単純化する方法はありますか?

$(ls -l | grep ^- | wc -l) $(if [ $(ls -l | grep ^- | wc -l) -eq 1 ]; then echo "file"; else echo "files"; fi)

私の目的は、フォルダ内のファイルの数を印刷しますもし宣言すべき扱う複数形は2つの状況を管理します。

  • ファイル1個
  • 2ファイル

たとえば、my〜フォルダには3つのファイルが含まれているため、スクリプトは「files」という単語を印刷する必要があります。 my ~/Desktopにはファイルが1つしかないため、スクリプトは「files」を印刷する必要があります。

上記のコード行を書いて作業は完了しましたが、よりきれいでスマートな方法があると思いました。

ベストアンサー1

まず、より高速なコマンドを使用して正しい番号を見つけることができます。私のテストでは、これはfind . -maxdepth 1 -type f -not -name '.*' | wc -l(約4:3)よりも速いことがわかりました。ls -l | grep '^-' | wc -lファイルも非表示にするには、検索部分を使用または省略するls -a必要があります。-not -name '.*'

次に、ファイルを2回計算する代わりに、結果を変数に保存して再利用します。

$(count=$(find . -maxdepth 1 -type f -not -name '.*' | wc -l)
  if [[ "$count" -eq 1 ]]; then
    echo "1 file"
  else
    echo "$count files"
  fi)

ご覧のとおり、サブシェルを使用する必要があります。それ以外の場合は、2番目のコマンドで変数を使用できません。私もここではなく[[ ... ]]bash固有のものを使用しました[ ... ]。一般的に言えば、これはより良い解決策です。

最後に、Bash変数を使用して$PROMPT_COMMANDプロンプトを印刷する前にいくつかのコードを実行することもできます。$PS1これにより、すべてのコードを変数に保存する必要がなくなります$PS1。変数$countは次のとおりです。グローバルしかし。次のように見えます。

function count_files () {
  __count=$(find . -maxdepth 1 -type f -not -name '.*' | wc -l)
  if [[ "$__count" -eq 1 ]]; then
    __plural=
  else
    __plural=s
  fi
}
PROMPT_COMMAND=count_files
PS1='other stuff $__count file$__plural more stuff'

しかし、これらのステップのどれを単純化すると考えるかは不明です。 :)

編集する

ちょうど見つけたこのスレッド。次のようにファイル数を計算するために使用できます。

function count_files () {
  local name
  __count=0
  for name in *; do
    [[ -f "$name" ]] && ((__count++))
  done
  # like above ...
}

検索バージョンより約1:13ほど高速です。これは少数のプロセスを開始するため、男性的です(findバージョンがlsバージョンよりも速い理由と同じです)。トレッドには別のextglobソリューションがあります。それはすべてあなたがファイルを望むか、ファイルへのリンクを望むかによって異なります。繰り返しますが、コードは速くなりましたが、今はもっと複雑に見えます。では、どのような「シンプルさ」を目指していますか?

編集2

私がコメントで言ったことにもかかわらず、プロセスを開始するオーバーヘッドは、ソートする必要がある場合、ソートするオーバーヘッドに比べておそらく小さいでしょう。たくさん/usr/bin/ファイルの場合、約2500個のファイルを含むコードを実行すると表示が開始されます。

おすすめ記事