Grep во многих каталогах, но искать только в конкретном подкаталоге каждого каталога, а не во всех подкаталогах

Мой случай:

dir1 
  subdir1
      FooFile
  subdir2

dir2 
  subdir1
      FooFile
  subdir2

Итак, если я cd dir1, я могу легко сделать что-то вроде find . | xargs grep "Foo", чтобы перечислить имена всех файлов, содержащих Foo.

Проблема в том, что существует так много подкаталогов и файлов, что этот поиск занимает очень много времени. Я хотел бы рекурсивно зайти в каждый основной каталог, а затем перейти только к ОДНОМУ подкаталогу (subdir1) и затем выполнить grep.

Каков наилучший способ перечислить имена всех файлов, содержащих Foo, из всех каталогов? Для каждого каталога с разными именами, subdir1 всегда находится на один уровень ниже dir1, и всегда называется subdir1 точно.

0
16.03.2016, 13:14
3 ответа

Вы можете сделать это с помощью сценария, например,

#!/bin/sh
find . -type d | while IFS= read -r pathname
do
    for name in "$pathname"/subdir1/*Foo*
    do
        [ -f "$name" ] && echo "$name"
    done
done

с обычными оговорками о новых строках в именах путей. Протестировано с помощью этого дерева:

./dir2
./dir2/subdir1
./dir2/subdir1/FooFile
./dir2/subdir2
./subdir1
./subdir1/FooFile
./dir spacew
./dir spacew/subdir1
./dir spacew/subdir1/FooFile
./dir spacew/subdir2
./dir1
./dir1/subdir1
./dir1/subdir1/FooFile

созданный скрипт

./subdir1/FooFile
./dir2/subdir1/FooFile
./dir spacew/subdir1/FooFile
./dir1/subdir1/FooFile

Вопрос был неоднозначным относительно использования grep (как написано, не было никакой разницы по сравнению с echo , за исключением возможности использования регулярных выражений вместо подстановочных знаков оболочки). В качестве альтернативы вы можете напрямую использовать grep :

#!/bin/sh
find . -type f -name '*Foo*' | grep -E 'subdir1/Foo[^/]*$' | while IFS= read -r pathname
do
    echo "$pathname"
done

Дальнейшее чтение:

0
28.01.2020, 02:35

Если вы хотите посмотреть в ] и в всех (подкаталогах) с именем subdir1 , которые на один уровень ниже верхнего уровня, вы можете сделать

find */subdir1 …

. Если вы ищете файлы, у которых names содержат Foo , вы можете сделать

find */subdir1 -type f -name "*Foo*" -print

Или вы можете сделать

find */subdir1 -type f -print | grep "Foo"

, но это будет включать каждый файл в каталоге , имя которого включает строка Foo , например, dir42 / subdir1 / Foods_I_Like / pizza и dir42 / subdir1 / Foods_I_Like / курица .

Если вы ищете файлов, содержащих Foo (т. Е., чье содержимое содержит Foo ), вы можете сделать

find */subdir1 -type f -print | xargs grep "Foo"

Примечания:

  • Это работает, потому что синопсис (использование) find выглядит так: {{ 1}}
     найти  [ параметры ] [ начальная точка ... ] [ выражение ] 
    т. Е. Вы можете вызвать find один раз в нескольких начальных точках; как в:
     найти  dir1 / subdir1 dir2 / subdir1 [ выражение ] 
  • Это обрабатывает файлы и каталоги, имена которых включают пробелы просто хорошо.
  • Если вы ищете файлы или каталог , имена которых содержат Foo , не включайте -тип f в соответствующих командах. .
  • Конечно, вы должны цитировать "* Foo *" и не должны цитировать * / subdir1 . Цитирование "Foo" необязательно - это не повредит, но вам не нужно цитировать слова, не содержащие специальных символы.
  • Вы можете не указывать -print , поскольку это действие по умолчанию.
1
28.01.2020, 02:35

что насчет

grep "foo" */subdir1/*  */subdir1/.*

? (исходя из вашего текущего вопроса, это кажется подходящим вариантом. если только не существует так много поддиректорий "subdir1", что оболочка не может предоставить весь список для grep.

Вы можете добавить -q и проверить, выйдет ли он с 0, если вы просто хотите посмотреть, появляется ли "foo" в файле

Вы также можете сделать рекурсивный grep, а затем отбросить то, что вам не нужно (тяжело для i/o, но просто) :

grep -r "foo" . | grep "^\./[^/][^/]*/subdir1/[^/][^/]*:"

(См. комментарии ниже: здесь, даже если имя содержит ":", это будет работать, так как вы нашли имя файла в поддиректории subdir1, и этот файл содержит foo. Однако он может пропустить файл, содержащий новую строку в имени, так как во втором grep он не увидит первое имя "./firstleveldir/", поэтому второй grep отклонит его...)

.
2
28.01.2020, 02:35

Теги

Похожие вопросы