web-dev-qa-db-fra.com

Comptez les fichiers dans un répertoire par extension

Dans le but de tester, j'aimerais compter le nombre de fichiers d'images dans un répertoire, séparant chaque type de fichier image par extension de fichier (jpg = "oui". Ceci parce que plus tard, il sera utile pour un autre script qui exécutera une action sur chaque extension de fichier). Puis-je utiliser quelque chose comme ce qui suit pour seuls les fichiers JPEG?

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

Considérant les extensions de fichiers JPG, PNG, BMP, RAW et d'autres, devrais-je utiliser un cycle while pour le faire?

16
watchmansky

Je suggérerais une approche différente, en évitant les éventuels problèmes de division de mots de 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

Vous pouvez boucler sur le tableau files avec des autres commandes que vous souhaitez effectuer sur les fichiers de chaque extension.


Plus de manière significative - ou pour des coquilles qui ne fournissent pas des tableaux explicitement - vous pouvez réutiliser le tableau de paramètres de position de Shell I.e.

set -- *."$ext"

puis remplacer ${#files[@]} et ${files[@]} avec $# et "$@"

14
steeldriver

Mon approche serait:

  1. Énumérez tous les fichiers du répertoire
  2. Extraire leur extension
  3. Trier le résultat
  4. Compter les occurrences de chaque extension

Une sorte de comme ceci (dernier awk appel est purement pour la mise en forme):

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

(en supposant =GNU ls ici pour le -U Option pour sauter le tri comme optimisation. Il peut être supprimé en toute sécurité sans affecter la fonctionnalité s'il n'est pas pris en charge).

26
groxxda

Cela traverse récursivement des fichiers et compte des extensions correspondant à:

$ 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
11
Kit
find -type f | sed -e 's/.*\.//' | sort | uniq -c
6
Neik

Tout ce qui implique ls est susceptible de produire des résultats inattendus avec des caractères spéciaux (espace et autres symboles). Toute bashism (comme des tableaux comme) n'est pas portable. Tout ce qui implique while read est généralement lent.

D'autre part, find est très flexible (beaucoup d'options à filtrer), il a [au moins] deux syntaxes qui échouent sans danger pour les caractères spéciaux ... et il échoue bien sur le grand répertoire.

Pour cet exemple, j'ai utilisé -iname Pour correspondre à un nom d'extension majuscule et minuscule. J'ai aussi limité le -maxdepth 1 Pour respecter votre question "dans le répertoire actuel" de votre question. Plutôt que de compter le nombre de lignes, où les noms de fichiers pourraient inclure CR/LF, -print0 Imprimera un octet nul à la fin de chaque nom de fichier ... alors | tr -d -c "\000" | wc -l Comptez avec précision des fichiers (NULL BYTES!).

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

P.s. -print0 | tr -d -c "\000" | wc -c peut être remplacé par -printf "\000" | wc -c ou même -printf '\n' | wc -l.

3
Franklin Piat

Peut-être qu'il peut devenir plus court

exts=( *.jpg *.png *.gif ); printf "There are ${#exts[@]}" extensions;
3
Valentin Bajrami

Je voulais juste obtenir le total:

find ./ -type f | sed -e 's/.*\.//' |  uniq -c | sort -u | awk '{print $1}' | awk '{total = total + $1}END{print total}'

sortir:

2347623
0
Mike Q

peut simplement utiliser ls pour quelque chose de ce simple imo

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

ou

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

ou

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

Si vous êtes sûr de l'extension, vous pouvez aller avec find comme

find *.jpeg | wc -l
0
Nithish JV