Contar arquivos em um diretório por extensão

10

Para fins de teste, eu gostaria de contar quantos arquivos de imagens estão dentro de um diretório, separando cada tipo de arquivo de imagem por extensão de arquivo (jpg="yes". Isso porque mais tarde será útil para outro script executar uma ação em cada extensão de arquivo). Posso usar algo como o seguinte apenas para arquivos JPEG?

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

Considerando as extensões de arquivo jpg, png, bmp, raw e outras, devo usar um ciclo while para fazer isso?

    
por watchmansky 26.07.2014 / 21:17

9 respostas

13

Eu sugeriria uma abordagem diferente, evitando os possíveis problemas de divisão de palavras 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

Você pode percorrer a matriz files com qualquer outro comando que você deseja executar nos arquivos de cada extensão específica.

    
por 26.07.2014 / 21:29
20

Minha abordagem seria:

  1. Listar todos os arquivos no diretório
  2. Extraia sua extensão
  3. Classifique o resultado
  4. Conte as ocorrências de cada extensão

Mais ou menos assim (a última chamada awk é puramente para formatação):

ls -U | awk -F . '{print $NF}' | sort | uniq -c | awk '{print $2,$1}'
    
por 26.07.2014 / 21:22
7

Isso recursivamente percorre arquivos e conta as extensões correspondentes:

$ 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
    
por 15.08.2017 / 03:56
3
find -type f | sed -e 's/.*\.//' | sort | uniq -c
    
por 22.10.2015 / 17:56
3

Qualquer coisa que envolva ls provavelmente produzirá resultados inesperados com caracteres especiais (espaço e outros símbolos). Qualquer bashismo (como matrizes) não é portátil. Qualquer coisa que envolva while read geralmente é lenta.

Por outro lado, find é MUITO flexível (muitas opções para filtrar), tem [pelo menos] duas sintaxes que não são seguras para caracteres especiais ... e Ele escala bem em um diretório grande.

Neste exemplo, usei -iname para corresponder ao nome da extensão de maiúsculas e minúsculas. Eu também restrinjai o -maxdepth 1 a respeitar a sua pergunta "no diretório atual". Em vez de contar o número de linhas, onde os nomes de arquivos podem incluir CR / LF, -print0 imprimirá um byte NULL no final de cada nome de arquivo ... então | tr -d -c "-print0 | tr -d -c "-printf "-printf '\n' | wc -l0" | wc -c0" | wc -c0" | wc -l está contando arquivos com precisão (bytes NULOS!).

extensions="jpg png gif"
for ext in $extensions; do
  c=$(find . -maxdepth 1 -iname "*.$ext" -print0 | tr -d -c "
extensions="jpg png gif"
for ext in $extensions; do
  c=$(find . -maxdepth 1 -iname "*.$ext" -print0 | tr -d -c "%pre%0" | 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
0" | 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. %code% pode ser substituído por %code% ou mesmo %code% .

    
por 27.04.2015 / 23:16
2

Talvez seja mais curto

exts=( *.jpg *.png *.gif ); printf "There are ${#exts[@]}" extensions;
    
por 26.07.2014 / 23:36
1

pode apenas usar o ls para algo tão simples como o 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
    
por 12.05.2018 / 04:44
0

Se tiver certeza da extensão, você pode ir com find like

find *.jpeg | wc -l
    
por 31.01.2019 / 12:50
0

Eu só queria saber o total:

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

saída:

2347623
    
por 26.03.2019 / 17:48