Есть по существу два метода, которые вы можете использовать для этого. Один будет анализировать строку, в то время как другой будет работать с каждым файлом. Для разбора строки используйте такой инструмент, как grep
, sed
или awk
, очевидно, он будет быстрее, но вот пример, показывающий оба, а также то, как вы можете «профилировать» 2 метода.
Пример данных
Для примеров ниже мы будем использовать следующие данные
$ touch dir{1..3}/dir{100..112}/file{1..5}
$ touch dir{1..3}/dir{100..112}/nile{1..5}
$ touch dir{1..3}/dir{100..112}/knife{1..5}
Удалить некоторые *f*
файлы из dir1/*
:
$ rm dir1/dir10{0..2}/*f*
Подход № 1 - Разбор через строки
Здесь мы будем использовать следующие инструменты, find
, grep
, и sort
.
$ find . -type f -name '*f*' | grep -o "\(.*\)/" | sort -u | head -5
./dir1/dir103/
./dir1/dir104/
./dir1/dir105/
./dir1/dir106/
./dir1/dir107/
Подход № 2 - Разбор с использованием файлов
Та же цепочка инструментов, что и раньше, но на этот раз мы будем использовать dirname
вместо grep
.
$ find . -type f -name '*f*' -exec dirname {} \; | sort -u | head -5
./dir1/dir103
./dir1/dir104
./dir1/dir105
./dir1/dir106
./dir1/dir107
ПРИМЕЧАНИЕ. Приведенные выше примеры используются head -5
для того, чтобы просто ограничить объем вывода, с которым мы имеем дело в этих примерах. Обычно они удаляются, чтобы получить полный список!
Сравнивая результаты
Мы можем использовать, time
чтобы взглянуть на 2 подхода.
имя_директории
real 0m0.372s
user 0m0.028s
sys 0m0.106s
Grep
real 0m0.012s
user 0m0.009s
sys 0m0.007s
Поэтому всегда лучше разбираться со строками, если это возможно.
Альтернативные методы анализа строк
grep & PCRE
$ find . -type f -name '*f*' | grep -oP '^.*(?=/)' | sort -u
СЭД
$ find . -type f -name '*f*' | sed 's#/[^/]*$##' | sort -u
AWK
$ find . -type f -name '*f*' | awk -F'/[^/]*$' '{print $1}' | sort -u
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