Кількість файлів у каталозі за розширенням


15

Для тестування я хотів би порахувати, скільки файлів зображень знаходиться у каталозі, розділяючи кожен тип файлу зображення на розширення файлу (jpg = "так". Це тому, що пізніше це буде корисно для іншого сценарію, який буде виконувати дію на кожному розширенні файлу). Чи можу я використовувати щось на зразок наступного лише для файлів 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}'

(припускаючи GNU lsтут для -Uможливості пропустити сортування як оптимізацію. Його можна безпечно видалити, не впливаючи на функціональність, якщо він не підтримується).


mhmh ... пізніше я повинен фільтрувати кожне знайдене розширення, щоб зробити для нього дію?
watchmansky

Це залежить від того, що ви хочете зробити в підсумку. Чи можете ви дати більше інформації?
groxxda

Моя мета: скрипт, який обробляє кожен файл розширення (лише файл зображення), змінюючи розмір від вхідних даних користувача. Отже, я починаю з того, скільки там файлів jpg, наступного png тощо
watchmansky

Рішення steeldrivers може бути більш підходящим.
groxxda

2
У мене були JPGі jpgфайли, і я хотів, щоб це було рекурсивно, тому моє рішення було написати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

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

3
Не забудьте початковий каталог із find. Крім того, це може допомогти майбутнім читачам цих відповідей, якщо ви дасте коротке пояснення свого рішення (на випадок, якщо вони захочуть його змінити для дещо іншого випадку).
Jeff Schaller

Наскільки добре це рішення стосується імен шляхів, що містять пробіли? Нові рядки?
dhag

1
findза замовчуванням для поточного каталогу, саме тому я цим користуюся. Я не думаю, що Бог задумав імена файлів, щоб у них було пробіли, але це добре працює для цього випадку. Якщо у вас є нові рядки, то ви заслуговуєте на все, що отримуєте. Я подумав над поясненням, але вирішив, що це дасть відповідь занадто довго, я думаю, що важлива простота. 99% випадків за 1% часу. Це, мабуть, версія 7 сумісна.
Неїк


3

Все, що стосується ls, швидше за все, дасть неочікувані результати за допомогою спеціальних символів (пробіл та інші символи). Будь-який башизм (як масиви) не є портативним. Все, що стосуєтьсяwhile readЗазвичай відбувається повільно.

З іншого боку, findДУЖЕ гнучка (багато варіантів для фільтрації), вона має [принаймні] два синтаксиси, які не є безпечними для спеціальних символів ... і він добре масштабується у великих каталогах.

У цьому прикладі я використовував -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

може просто використовувати 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і він рахується двічі замість одного разу. Або ще гірше, хтось робитьmkdir directory.jpeg; touch directory.jpeg/{1..100}.txt
Джефф Шаллер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.