Получить список подкаталогов, содержащих файл, соответствующий строке

Как я могу получить список подкаталогов, содержащих файл, соответствующий определенной строке?

Более конкретно, я ищу каталоги, содержащие файл с буквой «f», где-то встречающийся в имени файла.

В идеале, список не будет иметь дубликатов и содержать только путь без имени файла.

5 Solutions collect form web for “Получить список подкаталогов, содержащих файл, соответствующий строке”

find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort |uniq 

Вышеприведенное находит все файлы под текущим каталогом ( . ), -type f являются обычными файлами ( -type f ) и имеют f где-то в их имени ( -name '*f*' ). Затем sed удаляет имя файла, оставляя только имя каталога. Затем список каталогов сортируется ( sort ) и дубликаты удаляются ( uniq ).

Команда sed состоит из одной замены. Он ищет совпадения с регулярным выражением /[^/]+$ и заменяет все, что соответствует ничто. Знак доллара означает конец строки. [^/]+' означает один или несколько символов, которые не являются косой чертой. Таким образом, /[^/]+$ означает, что все символы из последней косой черты до конца строки. Другими словами, это соответствует имени файла в конце полного пути. Таким образом, команда sed удаляет имя файла, оставляя неизменным имя каталога, в котором находился файл.

Упрощения

Многие современные команды sort поддерживают флаг -u который делает uniq ненужным:

 find . -type f -name '*f*' | sed -r 's|/[^/]+$||' |sort -u 

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

 find . -type f -name '*f*' -printf '%h\n' | sort -u 

Более надежная версия (требуется инструмент GNU)

Вышеупомянутые версии будут смущены именами файлов, которые включают в себя новые строки. Более надежным решением является сортировка по строкам с nul-terminated:

 find . -type f -name '*f*' -printf '%h\0' | sort -zu | sed -z 's/$/\n/' 

Почему бы не попробовать это:

 find / -name '*f*' -printf "%h\n" | sort -u 

Для этого вы можете использовать 2 метода. Один будет разбирать строку, а другой будет работать с каждым файлом. Разбор строки использует такой инструмент, как 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 чтобы взглянуть на два подхода.

имя_директории

 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 

Вот один, который я нахожу полезным:

 find . -type f -name "*somefile*" | xargs dirname | sort | uniq 

Этот ответ бесстыдно основан на ответе slm. Это был интересный подход, но он имеет ограничение, если имена файлов и / или каталогов имеют специальные символы (пробел, полуколономер …). Хорошей привычкой является использование find /somewhere -print0 | xargs -0 someprogam find /somewhere -print0 | xargs -0 someprogam .

Пример данных

В приведенных ниже примерах мы будем использовать следующие данные

 mkdir -p dir{1..3}/dir\ {100..112} touch dir{1..3}/dir\ {100..112}/nile{1..5} touch dir{1..3}/dir\ {100..112}/file{1..5} touch dir{1..3}/dir\ {100..112}/kni\ fe{1..5} 

Удалите некоторые из *f* файлов из dir1/*/ :

 rm dir1/dir\ 10{0..2}/*f* 

Подход №1 – Анализ с использованием файлов

 $ find -type f -name '*f*' -print0 | sed -e 's#/[^/]*\x00#\x00#g' | sort -zu | xargs -0 -n1 echo | head -n5 ./dir1/dir 103 ./dir1/dir 104 ./dir1/dir 105 ./dir1/dir 106 ./dir1/dir 107 

ПРИМЕЧАНИЕ . В приведенных выше примерах используется head -5 чтобы просто ограничить объем вывода, с которым мы имеем дело для этих примеров. Их обычно удаляют, чтобы получить полный список! также замените echo которое любая команда вы хотите использовать.

  • как сделать поиск текста на терминале напрямую
  • Полнотекстовая индексация командной строки?
  • В чем разница между поиском. и найти . -Распечатать
  • Как исключить папки proc и sys из поиска с помощью команды find?
  • Как заменить список заполнителей в текстовом файле?
  • Поиск строк в файлах
  • Прямые результаты команды «Найти» для javac
  • apropos regex начать с?
  • Как я могу превратить инструмент `file` в предикат для` find`?
  • Помощь в командах UNIX - найти
  • «Find» пересекает каталог, если используется «-not -path» * / FolderName / * "'?
  • Как сделать многострочный поиск и заменить текст (удалить) рекурсивно
  • Interesting Posts

    sed для поиска нескольких слов и удаления этих строк

    Почему установка wiki для мультимедиа прекращается?

    Mutt scripting: интерактивный диалоговый макрос с использованием `dialog`

    Получение статистики ввода-вывода дисков для одиночного процесса в Linux

    Проблемы при объединении многих текстовых файлов рядом с пастой

    Списки каталогов ext4 в виде файла

    Как найти HD-файлы, связанные с точкой монтирования

    Вставьте новую строку перед каждой строкой, соответствующей шаблону, если предыдущая строка уже не указана

    Есть ли в Linux команда для запроса имени хоста с сервера WINS

    Что я должен ожидать, если переключиться с Ubuntu на openSuse

    Openbox menu.xml: возможно использование клавиатурных ускорителей?

    Как начать телефонный звонок с терминала в телефоне Ubuntu?

    Проверьте, какой процесс выдает среднюю нагрузку сверху

    веб-камера начинает висит os

    Проблема с командами столбца и цветовыми кодами

    Linux и Unix - лучшая ОС в мире.