На машине Linux я хотел бы пройти по иерархии папок и получить список всех отдельных расширений файлов в ней.
Как лучше всего добиться этого из оболочки?
На машине Linux я хотел бы пройти по иерархии папок и получить список всех отдельных расширений файлов в ней.
Как лучше всего добиться этого из оболочки?
Попробуйте это (не уверен, что это лучший способ, но он работает):
find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
Это работает следующим образом:
.svn
), используйте find . -type f -path '*/.svn*' -prune -o -print | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
источник
- person Dennis Golomazov; 22.11.2012
.bashrc
, вы должны экранировать $1
как \$1
. На самом деле кажется, что экранирование $1
тоже не вредит консольному использованию.
- person jakub.g; 04.12.2015
git ls-tree -r HEAD --name-only
вместо find
- person jakub.g; 04.12.2015
theme
из page_manager.theme.inc
.
- person user151841; 05.01.2016
find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort | uniq -c | sort -n
- person marcovtwout; 17.05.2016
configs-0.1.6
, у которых нет расширений, но есть точки в имени.
- person mrgloom; 03.04.2019
perl -ne 's/.+\.// && print'
- person blueray; 15.07.2021
Нет необходимости в канале для sort
, awk может все это сделать:
find . -type f | awk -F. '!a[$NF]++{print $NF}'
alias
, но сама команда уже использует кавычки в команде find. Чтобы исправить это, я бы использовал синтаксис буквальной строки bash
следующим образом: alias file_ext=$'find . -type f -name "*.*" | awk -F. \'!a[$NF]++{print $NF}\''
- person SiegeX; 14.03.2015
maindir/test.dir/myfile
- person Nelson Teixeira; 02.04.2017
-printf "%f\n"
в конец команды «найти» и повторно запустите тест.
- person SiegeX; 03.04.2017
Рекурсивная версия:
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
Я основал это на этом сообщение на форуме, кредит должен быть там.
git show --name-only --pretty="" | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u
- person vulcan raven; 03.02.2020
Powershell:
dir -recurse | select-object extension -unique
Спасибо http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html
.
(например, jquery-1.3.4
будет отображаться как .4
в выводе). Измените на dir -file -recurse | select-object extension -unique
, чтобы получать только расширения файлов.
- person mcw; 05.03.2018
Моя альтернатива без awk, sed, без Perl, без Python, совместимая с POSIX:
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
uniq
не имеет полного флага --count
, но -c
работает нормально
- person worc; 28.01.2020
find . -type f -name '*.?* .... '
, не полностью протестирован, но должен работать.
- person Ondra Žižka; 27.09.2020
Найдите все с точкой и покажите только суффикс.
find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u
если вы знаете, что все суффиксы имеют 3 символа, тогда
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
-name "."
, потому что это то, что уже есть
- person SiegeX; 24.08.2011
Добавляю в микс свою вариацию. Я думаю, что это самый простой вариант, и он может быть полезен, когда эффективность не имеет большого значения.
find . -type f | grep -oE '\.(\w+)$' | sort -u
$ find . -type f | grep -o -E '\.[^.\/]+$' | sort -u
- person mMontu; 09.12.2013
$ find . -type f | grep -Eo '\.(\w+)$' | sort -u
. Исходный показывает файлы без расширения, в моем случае это было не то, что мне нужно.
- person Fernando Crespo; 17.03.2021
Я попробовал здесь несколько ответов, даже лучший ответ. Все они не соответствовали тому, что мне было нужно. Итак, помимо последних 12 часов сидения в коде регулярных выражений для нескольких программ, чтения и тестирования этих ответов, это то, что я придумал, и который работает ТОЧНО, как я хочу.
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
Если вам нужно количество расширений файлов, используйте приведенный ниже код
find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn
Хотя выполнение этих методов займет некоторое время и, вероятно, не является лучшим способом решения проблемы, они работают.
Обновление: длинные расширения файлов Per @ 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 - длина расширений файла, которые нужно включить, а затем найти любые расширения, превышающие эту длину.
В 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)
Поскольку уже существует другое решение, использующее 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
Я думаю, что самый простой и понятный способ - это
for f in *.*; do echo "${f##*.}"; done | sort -u
Он модифицирован 3-м способом ChristopheD.
Я не думаю, что об этом еще упоминали:
find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c
вы также можете сделать это
find . -type f -name "*.php" -exec PATHTOAPP {} +
Я нашел это просто и быстро ...
# find . -type f -exec basename {} \; | awk -F"." '{print $NF}' > /tmp/outfile.txt
# cat /tmp/outfile.txt | sort | uniq -c| sort -n > tmp/outfile_sorted.txt
В принятом ответе используется REGEX, и вы не можете создать команду псевдонима с помощью REGEX, вы должны поместить ее в сценарий оболочки, я использую Amazon Linux 2 и сделал следующее:
Я поместил принятый код ответа в файл, используя:
sudo vim find.sh
добавьте этот код:
find ./ -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u
сохраните файл, набрав: :wq!
sudo vim ~/.bash_profile
alias getext=". /path/to/your/find.sh"
:wq!
. ~/.bash_profile
По-другому:
find . -type f -name "*.*" -printf "%f\n" | while IFS= read -r; do echo "${REPLY##*.}"; done | sort -u
Вы можете опустить -name "*.*"
, но это гарантирует, что мы будем иметь дело только с файлами, у которых есть какое-то расширение.
-printf
- это print find
, а не bash. -printf "%f\n"
печатает только имя файла, удаляя путь (и добавляя новую строку).
Затем мы используем подстановку строк, чтобы удалить до последней точки, используя ${REPLY##*.}
.
Обратите внимание, что $REPLY
- это просто встроенная переменная read
. Мы могли бы точно так же использовать нашу собственную в форме: while IFS= read -r file
, и здесь $ file будет переменной.