Как найти все различные расширения файлов в иерархии папок?

StackOverflow https://stackoverflow.com/questions/1842254

Вопрос

На машине с Linux я хотел бы просмотреть иерархию папок и получить список всех различных расширений файлов внутри нее.

Как лучше всего добиться этого из оболочки?

Это было полезно?

Решение

Попробуйте это (не уверен, что это лучший способ, но он работает):

find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

Это работает следующим образом:

  • Найти все файлы из текущей папки
  • Печатает расширение файлов, если оно есть.
  • Создайте уникальный отсортированный список

Другие советы

Нет необходимости в трубе sort, awk может все это:

find . -type f | awk -F. '!a[$NF]++{print $NF}'

Рекурсивная версия:

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u

Если вам нужны итоговые данные (сколько раз расширение было замечено):

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

Нерекурсивный (одна папка):

for f in *.*; do printf "%s\n" "${f##*.}"; done | sort -u

Я основывал это на это сообщение на форуме, кредит должен идти туда.

Powershell:

dir -recurse | select-object extension -unique

Благодаря http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html

Найдите все, что отмечено точкой, и покажите только суффикс.

find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u

если вы знаете, что все суффиксы состоят из трех символов, тогда

find . -type f -name "*.???" | awk -F. '{print $NF}' | sort -u

или с помощью sed отображаются все суффиксы, содержащие от одного до четырех символов.Измените {1,4} на диапазон символов, которые вы ожидаете в суффиксе.

find . -type f | sed -n 's/.*\.\(.\{1,4\}\)$/\1/p'| sort -u

Добавляю в микс свою собственную вариацию.Я думаю, что это самый простой из всех вариантов, и он может быть полезен, когда эффективность не имеет большого значения.

find . -type f | grep -o -E '\.[^\.]+$' | sort -u

Моя POSIX-совместимая альтернатива без awk, без sed, без Perl и Python:

find . -type f | rev | cut -d. -f1 | rev  | tr '[:upper:]' '[:lower:]' | sort | uniq --count | sort -rn

Хитрость в том, что он переворачивает строку и обрезает расширение в начале.
Он также преобразует расширения в нижний регистр.

Пример вывода:

   3689 jpg
   1036 png
    610 mp4
     90 webm
     90 mkv
     57 mov
     12 avi
     10 txt
      3 zip
      2 ogv
      1 xcf
      1 trashinfo
      1 sh
      1 m4v
      1 jpeg
      1 ini
      1 gqv
      1 gcs
      1 dv

В Python используются генераторы для очень больших каталогов, включая пустые расширения, и получаются сведения о том, сколько раз появляется каждое расширение:

import json
import collections
import itertools
import os

root = '/home/andres'
files = itertools.chain.from_iterable((
    files for _,_,files in os.walk(root)
    ))
counter = collections.Counter(
    (os.path.splitext(file_)[1] for file_ in files)
)
print json.dumps(counter, indent=2)

Я попробовал здесь кучу ответов, даже «лучший» ответ.Все они не соответствовали тому, чего я конкретно добивался.Итак, помимо последних 12 часов сидения в коде регулярных выражений для нескольких программ, чтения и тестирования этих ответов, я придумал вот что, которое работает ТОЧНО так, как я хочу.

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
  • Находит все файлы, которые могут иметь расширение.
  • Greps только расширение
  • Greps для расширений файлов от 2 до 16 символов (просто измените цифры, если они не соответствуют вашим потребностям).Это помогает избежать файлов кэша и системных файлов (бит системного файла предназначен для поиска в тюрьме).
  • Awk для печати расширений в нижнем регистре.
  • Сортируйте и вводите только уникальные значения.Первоначально я пытался попробовать ответ awk, но он дважды печатал элементы, которые различались в зависимости от регистра.

Если вам нужно подсчитать расширения файлов, используйте приведенный ниже код.

find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn

Хотя эти методы потребуют некоторого времени для выполнения и, вероятно, не являются лучшими способами решения проблемы, они работают.

Обновлять:Согласно @alpha_989, длинные расширения файлов могут вызвать проблемы.Это связано с исходным регулярным выражением "[[:alpha:]]{3,6}".Я обновил ответ, включив в него регулярное выражение «[[:alpha:]]{2,16}».Однако любой, кто использует этот код, должен знать, что эти числа представляют собой минимальное и максимальное время, в течение которого расширение разрешено для окончательного вывода.Все, что находится за пределами этого диапазона, будет разделено на несколько строк при выводе.

Примечание:Исходное сообщение гласило: «- Greps для расширений файлов от 3 до 6 символов (просто измените цифры, если они не соответствуют вашим потребностям).Это помогает избежать файлов кеша и системных файлов (бит системного файла предназначен для поиска в тюрьме)».

Идея:Может использоваться для поиска расширений файлов определенной длины с помощью:

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u

Где 4 — длина расширений файла, которые необходимо включить, а затем найти любые расширения, превышающие эту длину.

Поскольку уже есть другое решение, использующее Perl:

Если у вас установлен Python, вы также можете сделать (из оболочки):

python -c "import os;e=set();[[e.add(os.path.splitext(f)[-1]) for f in fn]for _,_,fn in os.walk('/home')];print '\n'.join(e)"

Ни один из ответов до сих пор не касается имен файлов с символами новой строки (за исключением ответа ChristopheD, который пришел только тогда, когда я это печатал).Следующее не является однострочником оболочки, но работает и достаточно быстро.

import os, sys

def names(roots):
    for root in roots:
        for a, b, basenames in os.walk(root):
            for basename in basenames:
                yield basename

sufs = set(os.path.splitext(x)[1] for x in names(sys.argv[1:]))
for suf in sufs:
    if suf:
        print suf

Я думаю, что об этом еще не упоминалось:

find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c

Я думаю, что самый простой и понятный способ - это

for f in *.*; do echo "${f##*.}"; done | sort -u

Он модифицирован по третьему способу ChristopheD.

ты тоже можешь сделать это

find . -type f -name "*.php" -exec PATHTOAPP {} +
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top