Как выполнить рекурсивный поиск по каталогу для строк в файлах в среде UNIX TRU64? - PullRequest
2 голосов
/ 04 ноября 2010

К сожалению, из-за ограничений нашей среды Unix Tru64 я не могу использовать переключатель GREP -r для выполнения поиска строк в файлах по нескольким каталогам и подкаталогам.

В идеале я хотел бы передать два параметра. Первым будет каталог, в котором я хочу начать поиск. Второй - это файл, содержащий список всех строк, которые необходимо найти. Этот список будет состоять из различных имен каталогов и включать специальные символы:

есть:
/ Ааа / В / ссс
/ Еее / дддд / ggggggg /
и т.д ..

Цель этого упражнения - идентифицировать все сценарии оболочки, которые могут иметь конкретные жестко заданные пути, указанные в моем списке.

Был один пример, который я обнаружил во время своих расследований, который, возможно, близок, но я не уверен, как настроить его так, чтобы он принимал файл строковых аргументов:

Например: найти etb -exec grep test {} \;

где 'etb' - это каталог, а 'test' - жестко закодированная строка для поиска.

Ответы [ 2 ]

1 голос
/ 04 ноября 2010

Читая, я предполагаю, что мы не можем использовать gnu coreutil , и egrep недоступен.Я предполагаю (по какой-то причине), что система сломана, и выходы не работают должным образом.

В обычных ситуациях grep -rf patternfile.txt /some/dir/ - это путь.

файлсодержащий список всех строк для поиска

Допущения: gnu coreutil недоступен.grep -r не работает.обработка специального символа нарушена.

Теперь у вас работает awk?нет?Это делает жизнь намного проще.Но давайте будем в безопасности.

Предположим: работает sed, доступен один из od ИЛИ hexdump ИЛИ xxd (из пакета vim).

Позволяет вызывать этот patternfile.txt


1.Преобразуйте список в регулярное выражение, которое grep любит

Пример patternfile.txt содержит

/ foo /

/ bar / doe /

/ root/

(пример не печатает специальный символ, но он есть). Мы должны превратить его в нечто вроде

(/foo/|/bar/doe/|/root/)

Предполагая команду echo -enне сломан, и xxd, или od, или hexdump доступны,

Используя hexdump

cat patternfile.txt |hexdump -ve '1/1 "%02x \n"' |tr -d '\n'

Используя od

cat patternfile.txt |od -A none -t x1|tr -d '\n'

и передать его в канал (общий для hexdump и od) |sed 's:[ ]*0a[ ]*$::g'|sed 's: 0a:\\|:g' |sed 's:^[ ]*::g'|sed 's:^: :g' |sed 's: :\\x:g', затем передать результат в |sed 's:^:\\(:g' |sed 's:$:\\):g', и у вас есть шаблон регулярного выражения, который экранируется.


2.Заполните экранированный шаблон в неработающее регулярное выражение

Предполагая, что минимальный выход оболочки возможен, мы используем grep "$(echo -en "ESCAPED_PATTERN" )" для нашей работы.


3.Подводя итог:

Построение экранированного шаблона регулярного выражения (на примере hexdump)

grep "$(echo -en "$( cat patternfile.txt |hexdump -ve '1/1 "%02x \n"' |tr -d '\n' |sed 's:[ ]*0a[ ]*$::g'|sed 's: 0a:\\|:g' |sed 's:^[ ]*::g'|sed 's:^: :g' |sed 's: :\\x:g'|sed 's:^:\\(:g' |sed 's:$:\\):g')")"

будет экранировать все символы и заключать его в(|) в скобках, поэтому будет выполнено регулярное выражение ИЛИ.

4.Рекурсивный поиск в каталогах

В нормальных ситуациях, даже если grep -r не работает, find /dir/ -exec grep {} \; должен работать.Некоторые могут предпочесть xargs instaed (если только у вас не было глючных xargs).Мы предпочитаем find /somedir/ -type f -print0 |xargs -0 grep -f 'patternfile.txt' подход, но так как он недоступен (по какой-либо уважительной причине), нам нужно выполнить grep для каждого файла, и это обычно неправильный путь.Но давайте сделаем это.

Предположим: find -type f работает.Предположим: xargs сломан ИЛИ не доступен.

Во-первых, если у вас глючный канал, он может не обрабатывать большое количество файлов.Поэтому мы избегаем xargs в таких системах (я знаю, я знаю, просто давайте притворимся, что он сломан).

find /whatever/dir/to/start/looking/ -type f > list-of-all-file-to-search-for.txt

ЕСЛИ ваша оболочка прекрасно обрабатывает списки больших размеров, for file in cat list-of-all-file-to-search-for.txt ; do grep REGEXP_PATTERN "$file" ; done ; это хороший способ обойтись.К сожалению, некоторым системам это не нравится, и в этом случае вам может потребоваться cat list-of-all-file-to-search-for.txt | split --help -a 4 -d -l 2000 file-smaller-chunk.part., чтобы превратить его в более мелкие куски.Теперь это для серьезно сломанной системы.тогда for file in file-smaller-chunk.part.* ; do for single_line in cat "$file" ; do grep REGEXP_PATTERN "$single_line" ; done ; done ; должен работать.

A cat filelist.txt |while read file ; do grep REGEXP_PATTERN $file ; done ; может использоваться в качестве обходного пути на некоторых системах.

Что если моя оболочка не обрабатывает кавычки?

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

Это может быть сделано намного лучше в awk, perl, что угодно, но поскольку мы ограничиваем себя sed, давайте сделаем это.Мы предполагаем, что 0x27, the ' code действительно будет работать.cat list-of-all-file-to-search-for.txt |sed 's@['\'']@'\''\\'\'\''@g'|sed 's:^:'\'':g'|sed 's:$:'\'':g' Единственный раз, когда мне пришлось использовать это, было при подаче вывода в bash снова.

Что, если моя оболочка не справится с этим?

xargs завершится неудачей, grep -r завершится неудачей,Оболочка для цикла завершается неудачей.

Есть ли у нас другие вещи?ДА.

Избегайте ввода, подходящего для вашей оболочки, и создайте сценарий.

Но вы знаете, что у меня есть доска, и написание автоматических сценариев для csh кажется неправильным.Поэтому я остановлюсь здесь.

Возьмите домашнюю заметку

Используйте инструмент для правильной работы.Написание интерпретатора на bc вполне возможно, но это просто неправильно.Установите coreutils, perl, лучше grep, чем когда-либо.делает жизнь лучше.

1 голос
/ 04 ноября 2010

Это должно сделать это:

find dir -type f -exec grep -F -f strings.txt {} \;

dir - каталог, из которого начнется поиск

strings.txt - файл строк для сопоставления, по одному на строку

-F означает, что строки поиска рассматриваются как литеральные, а не регулярные выражения

-f strings.txt означает, что строки strings.txt используются для сопоставления

Вы можетедобавьте -l к переключателям grep, если вы просто хотите, чтобы имена файлов совпадали.

Сноска:

Некоторые люди предпочитают решение, включающее xargs, например

find dir -type f -print0 | xargs -0 grep -F -f strings.txt

, что в некоторых случаях, возможно, немного более надежно / эффективно.

...