Я хочу считать количество файлов для каждого расширения в каталоге, а также файлов без расширения.
Я попробовал несколько опций, но я еще не нашел рабочее решение:
find "$folder" -type f | sed 's/.*\.//' | sort | uniq -c
опция, но не работает, если нет никакого расширения файла. Я должен знать, сколько файлы не имеют расширением.
Я также попробовал цикл находки в массив и затем суммирую результаты, но в это время, которые кодируют, бросает необъявленную переменную погрешность, но только за пределами цикла:
declare -a arr
arr=()
echo ${arr[@]}
Это бросает необъявленную переменную, а также после того как цикл находки завершается.
find "$path" -type f | sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//' | LC_COLLATE=C sort | uniq -c
find "$path" -type f
получите рекурсивный список всех файлов на "$path"
папка.sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//'
регулярные выражения:
/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/
замените все файлы без расширения (ни одним).s/.*\.//
получите расширение остающихся файлов.LC_COLLATE=C sort
отсортируйте результат, сохранив символы наверху.uniq -c
считайте количество повторных записей.Использование Python:
import os
from collections import Counter
from pprint import pprint
lst = []
for file in os.listdir('./'):
name, ext = os.path.splitext(file)
lst.append(ext)
pprint(Counter(lst))
Вывод:
Counter({'': 7,
'.png': 4,
'.mp3': 3,
'.jpg': 3,
'.mkv': 3,
'.py': 1,
'.swp': 1,
'.sh': 1})
Если у Вас есть GNU awk, Вы могли бы сделать что-то как
printf '%s\0' * | gawk 'BEGIN{RS="\0"; FS="."; OFS="\t"}
{a[(NF>1 ? $NF : "(none)")]++}
END{for(i in a) print a[i],i}
'
т.е. создайте / увеличивают ассоциативный массив, включил последнее .
разделенное поле или некоторая произвольная фиксированная строка такой как (none)
если нет никакого расширения.
mawk
кажется, не позволяет разделитель записей пустого байта - Вы могли использовать mawk
с разделителем новой строки по умолчанию, если Вы уверены, что не должны иметь дело с новыми строками в своих именах файлов:
printf '%s\n' * | mawk 'BEGIN{FS="."; OFS="\t"} {a[(NF>1 ? $NF : "(none)")]++} END{for(i in a) print a[i],i}'
С основным /bin/sh
или даже bash
задача может быть немного трудной, но поскольку Вы видите в других ответах инструменты, которые могут работать над агрегированными данными, может иметь дело с такой особенно легкой задачей. Один такой инструмент был бы sqlite
база данных.
Очень простой процесс для использования sqlite
база данных должна была бы создать a .csv
файл с двумя полями: имя файла и расширение. Позже sqlite
может использовать простой совокупный оператор COUNT()
с GROUP BY ext
выполнить подсчет файлов на основе дополнительного поля
$ { printf "file,ext\n"; find -type f -exec sh -c 'f=${1##*/};printf "%s,%s\n" "${1}" "${1##*.}"' sh {} \; ; } > files.csv
$ sqlite3 <<EOF
> .mode csv
> .import ./files.csv files_tb
> SELECT ext,COUNT(file) FROM files_tb GROUP BY ext;
> EOF
csv,1
mp3,6
txt,1
wav,27
Используя PowerShell, если это - опция:
Get-ChildItem -File | Group-Object Extension -NoElement
или короче, использование псевдонимов:
ls -file | group -n Extension