ディレクトリ内のファイルを拡張子でカウントする


15

テストの目的で、ディレクトリ内の画像ファイルの数を数え、各画像ファイルの種類をファイル拡張子(jpg = "yes"で分けます。これは、後でアクションを実行する別のスクリプトに役立つためです。各ファイル拡張子で)。JPEGファイルのみに次のようなものを使用できますか?

jpg=""
count=`ls -1 *.jpg 2>/dev/null | wc -l`
if [ $count != 0 ]
then
echo jpg files found: $count ; jpg="yes"
fi

ファイル拡張子jpg、png、bmp、rawなどを考慮whileして、これを行うにはサイクルを使用する必要がありますか?

回答:


14

私は別のアプローチを提案し、可能性のある単語分割の問題を回避します ls

#!/bin/bash

shopt -s nullglob

for ext in jpg png gif; do 
  files=( *."$ext" )
  printf 'number of %s files: %d\n' "$ext" "${#files[@]}"

  # now we can loop over all the files having the current extension
  for f in "${files[@]}"; do
    # anything else you like with these files
    :
  done 

done

files特定の各拡張子のファイルに対して実行する他のコマンドを使用して、配列をループできます。


より移植性が高い-または明示的に配列を提供しないシェルの場合、シェルの位置パラメータ配列を再利用できます

set -- *."$ext"

その後、交換する${#files[@]}${files[@]}して$#"$@"


23

私のアプローチは次のとおりです。

  1. ディレクトリ内のすべてのファイルをリストする
  2. 拡張子を抽出する
  3. 結果を並べ替える
  4. 各拡張子の出現回数を数える

このような並べ替え(最後のawk呼び出しは純粋にフォーマット用です):

ls -q -U | awk -F . '{print $NF}' | sort | uniq -c | awk '{print $2,$1}'

(最適化としてソートをスキップlsする-Uオプションについては、ここでGNUを想定しています。サポートされていない場合、機能に影響を与えることなく安全に削除できます)。


mhmh ...後でアクションを実行するために見つかった各拡張機能をフィルタリングする必要がありますか?
watchmansky 14

最終的に何をしたいかによって異なります。さらに情報を提供できますか?
groxxda 14

私の目標:入力ユーザーデータからサイズを変更する各拡張ファイル(画像ファイルのみ)を処理するスクリプト。そこで、jpgファイルの数、次のpngなどから始めます。
watchmansky 14

steeldriversソリューションがより適切な場合があります。
groxxda 14

2
私は両方JPGjpgファイルを持っていたので、再帰的にそれを望んでいたので、私の解決策は書くことでしたfind . -type f | awk -F . '{print tolower($NF)}' | sort | uniq -c | awk '{print $2,":",$1}'
クリスチャン

11

これはファイルを再帰的に走査し、一致する拡張子をカウントします。

$ find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'
   6 tiff
   7 bmp
  26 jpeg
  38 gif
  51 jpg
  54 png

5
find -type f | sed -e 's/.*\.//' | sort | uniq -c

3
で始まるディレクトリを忘れないでくださいfind。また、ソリューションの簡単な説明を提供すると、これらの回答の将来の読者を助けることができます(わずかに異なるケースに合わせて修正したい場合)。
ジェフシャラー

このソリューションは、スペースを含むパス名をどの程度適切に処理しますか?改行?
dhag

1
findデフォルトは現在のディレクトリです。これが私がこれを使用する方法です。神がファイル名にスペースを入れることを意図したとは思いませんが、その場合はうまくいきます。改行がある場合、取得するすべてに値します。私は説明を考えましたが、答えが長すぎると判断しました。シンプルさが重要だと思います。1%の確率で99%のケース。これはおそらくバージョン7互換です。
ネイク


3

関係するものlsはすべて、特殊文字(スペースおよびその他の記号)で予期しない結果を生成する可能性があります。bashism(配列など)は移植性がありません。while read通常、関与するものはすべて低速です。

一方、find非常に柔軟性があり(フィルタリングするオプションがたくさんあります)、特殊な文字に対してはフェールセーフな[少なくとも] 2つの構文があります...そして、大きなディレクトリでうまく拡張できます。

この例では、-iname大文字と小文字の両方の拡張子名を一致させるために使用しました。また-maxdepth 1、質問の「現在のディレクトリ内」を尊重するように制限しています。ファイル名にCR / LFを含めることができる行数をカウントするのではなく-print0、各ファイル名の末尾にNULLバイトを出力します... | tr -d -c "\000" | wc -lファイルを正確にカウントします(NULLバイト!)。

extensions="jpg png gif"
for ext in $extensions; do
  c=$(find . -maxdepth 1 -iname "*.$ext" -print0 | tr -d -c "\000" | wc -c)
  if [ $c -gt 0 ]; then
    echo "Found $c  *.$ext files"

    find . -maxdepth 1 -iname "*.$ext" -print0 | xargs -0 -r -n1 DOSOMETHINGHERE
    # or #  find . -maxdepth 1 -iname "*.$ext" -exec "ls" "-l" "{}" ";"
  fi
done

PS -print0 | tr -d -c "\000" | wc -c-printf "\000" | wc -cまたはに置き換えることもできます-printf '\n' | wc -l


0

このシンプルなIMOにlsを使用できます

ls -l /opt/ssl/certs/*.pem | wc -l

または

count=$(ls -l /some/folder/*.jpg | wc -l)

または

ls *.{mp3,exe,mp4} 2>/dev/null | wc -l

-2

拡張機能が確かな場合は、次のfindようにできます

find *.jpeg | wc -l

誰かが作成touch $'foo\nbar.jpegし、1回ではなく2回カウントされるまで。さらに悪いことに、誰かがmkdir directory.jpeg; touch directory.jpeg/{1..100}.txt
ジェフシャラー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.