find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq
Вышеприведенное находит все файлы в текущей директории ( .
), которые являются обычными файлами ( -type f
) и имеют f
где-то свое имя ( -name '*f*'
). Далее sed
удаляет имя файла, оставляя только имя каталога. Затем список каталогов сортируется ( sort
) и удаляются дубликаты ( uniq
).
Команда sed
состоит из единственной замены. Он ищет совпадения с регулярным выражением /[^/]+$
и заменяет все, что соответствует этому, ничем. Знак доллара означает конец строки. [^/]+'
означает один или несколько символов, которые не являются косыми чертами. Таким образом, /[^/]+$
означает все символы от последней косой черты до конца строки. Другими словами, это соответствует имени файла в конце полного пути. Таким образом, команда sed удаляет имя файла, оставляя неизменным имя каталога, в котором находился файл.
Упрощения
Многие современные sort
команды поддерживают -u
флаг, который делает uniq
ненужным. Для GNU sed:
find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort -u
И, для MacOS SED:
find . -type f -name '*f*' | sed -E 's|/[^/]+$||' |sort -u
Кроме того, если ваша find
команда поддерживает это, можно find
распечатать имена каталогов напрямую. Это позволяет избежать необходимости sed
:
find . -type f -name '*f*' -printf '%h\n' | sort -u
Более надежная версия (требуются инструменты GNU)
Вышеуказанные версии будут сбиты с толку именами файлов, которые включают переводы строк. Более надежное решение - выполнить сортировку по NUL-завершенным строкам:
find . -type f -name '*f*' -printf '%h\0' | sort -zu | sed -z 's/$/\n/'
uniq
в микс очень помогает, удаляя повторяющиеся строки, которые уже находятся рядом друг с другом.find . -type f -name '*f*' -printf '%h\0' | uniq -z | sort -zu | tr '\0' '\n'
, Или, если ваши инструменты немного старше, то uniq может не иметь опции -z.find . -type f -name '*f*' -printf '%h\n' | uniq | sort -u
-E
для MacOS.Почему бы не попробовать это:
источник
find
довольно скудны --printf
оператор не указан. Это не работает с BSDfind
. Таким образом, не "полностью POSIX-совместимый". (Хотяsort -u
это в POSIX .)Есть по существу два метода, которые вы можете использовать для этого. Один будет анализировать строку, в то время как другой будет работать с каждым файлом. Для разбора строки используйте такой инструмент, как
grep
,sed
илиawk
, очевидно, он будет быстрее, но вот пример, показывающий оба, а также то, как вы можете «профилировать» 2 метода.Пример данных
Для примеров ниже мы будем использовать следующие данные
Удалить некоторые
*f*
файлы изdir1/*
:Подход № 1 - Разбор через строки
Здесь мы будем использовать следующие инструменты,
find
,grep
, иsort
.Подход № 2 - Разбор с использованием файлов
Та же цепочка инструментов, что и раньше, но на этот раз мы будем использовать
dirname
вместоgrep
.ПРИМЕЧАНИЕ. Приведенные выше примеры используются
head -5
для того, чтобы просто ограничить объем вывода, с которым мы имеем дело в этих примерах. Обычно они удаляются, чтобы получить полный список!Сравнивая результаты
Мы можем использовать,
time
чтобы взглянуть на 2 подхода.имя_директории
Grep
Поэтому всегда лучше разбираться со строками, если это возможно.
Альтернативные методы анализа строк
grep & PCRE
СЭД
AWK
источник
Вот один, который я считаю полезным:
источник
Этот ответ бесстыдно основан на ответе SLM. Это был интересный подход, но он имеет ограничение, если имена файлов и / или каталогов имели специальные символы (пробел, полуколонка ...). Хорошей привычкой является использование
find /somewhere -print0 | xargs -0 someprogam
.Пример данных
Для примеров ниже мы будем использовать следующие данные
Удалить некоторые
*f*
файлы изdir1/*/
:Подход № 1 - Разбор с использованием файлов
ПРИМЕЧАНИЕ . Приведенные выше примеры используются
head -5
для того, чтобы просто ограничить объем вывода, с которым мы имеем дело в этих примерах. Обычно они удаляются, чтобы получить полный список! также заменитеecho
какую команду вы хотите использовать.источник
С
zsh
:источник