Как делают меня рекурсивно grep через сжатые архивы?

Можно попробовать это:

ssh-add -L | awk '{ print $2 }' | xargs -i grep '{}' ~/.ssh/authorized_keys  | head -1
16
29.03.2016, 01:35
6 ответов

Хорошо, давайте применим философию Unix. Каковы компоненты этой задачи?

  • Текстовый поиск: Вам нужен инструмент к искомому тексту в файле, такой как grep.
  • Рекурсивный: Вам нужен инструмент для движения, ища файлы в дереве каталогов, такой как find.
  • Архивы: Вам нужен инструмент для чтения их.

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

Файловая система AVFS представляет представление файловой системы где каждый архивный файл /path/to/foo.zip доступно как каталог ~/.avfs/path/to/foo/zip#. AVFS обеспечивает доступ только для чтения к наиболее распространенным форматам архивного файла.

mountavfs
find ~/.avfs"$PWD" \( -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
     -exec sh -c '
                  find "$0#" -name "*.pm" -exec grep "$1" {\} +
                 ' {} 'Test::Version' \;
fusermount -u ~/.avfs   # optional

Объяснения:

  • Смонтируйте файловую систему AVFS.
  • Ищите архивные файлы в ~/.avfs$PWD, который является представлением AVFS текущего каталога.
  • Для каждого архива выполните указанный отрывок оболочки (с $0 = заархивируйте имя и $1 = шаблон для поиска).
  • $0# представление каталога архива $0.
  • {\} вместо {} необходим в случае, если внешнее find замены {} внутри -exec ; аргументы (некоторые делают это, некоторые не делают).
  • Дополнительный: наконец размонтируйте файловую систему AVFS.

Или в zsh ≥4.3:

mountavfs
grep 'Test::Version' ~/.avfs$PWD/**/*.(tgz|tar.gz|zip)(e\''
     reply=($REPLY\#/**/*.pm(.N))
'\')

Объяснения:

  • ~/.avfs$PWD/**/*.(tgz|tar.gz|zip) соответствия архивируют в представлении AVFS текущего каталога и его подкаталогов.
  • PATTERN(e\''CODE'\') применяет КОД к каждому соответствию ШАБЛОНА. Название подобранного файла находится в $REPLY. Установка reply массив превращает соответствие в список имен.
  • $REPLY\# представление каталога архива.
  • $REPLY\#/**/*.pm соответствия .pm файлы в архиве.
  • N спецификатор шарика заставляет шаблон расшириться до пустого списка, если там не идет ни в какое сравнение.
18
27.01.2020, 19:48
  • 1
    это создает другую intesting проблему необходимости смонтировать и затем размонтировать все архивы как часть проблема, - то, что существуют архивы 22k, которые должны быть перерыты –  xenoterracide 28.05.2011, 17:24
  • 2
    @xenoterracide: Как это - проблема? С AVFS у Вас есть единственная точка монтирования (~/.avfs), и доступ к каждому архиву является автоматическим (~/.avfs/path/to/archive.zip\# обычный каталог в файловой системе AVFS, не точка монтирования). Несомненно, каждый архив, к которому Вы получаете доступ, имеет в виду немного хита производительности, но это внутренне проблеме. красивый –  Gilles 'SO- stop being evil' 28.05.2011, 17:31
  • 3
    @gilles только то, что теперь я должен пройти и выяснить, как смонтировать их сначала, который походит на определенную плохую идею, лучше для монтирования их, когда я иду и размонтировался, ищась. –  xenoterracide 28.05.2011, 18:14
  • 4
    @xenoterracide: Снова: нет, Вы не должны монтировать их индивидуально. Полный рабочий процесс (кроме установки AVFS в случае необходимости) находится в моих фрагментах кода. –  Gilles 'SO- stop being evil' 28.05.2011, 18:18
  • 5
    @gilles хорошо, который я должен буду вырыть в это немного..., потому что я добираюсь find: missing argument to - должностное лицо'' и многое из этого от zsh zsh: Input/output error: Data-Maker-0.27 –  xenoterracide 28.05.2011, 18:36

Кажется, что я могу сделать это этот путь

find authors/ -type f -exec zgrep "Test::Version" '{}' +  

Однако это дает результаты как:

authors/id/J/JO/JONASBN/Module-Info-File-0.11.tar.gz:Binary file (standard input) matches

который не очень конкретен туда, где в tarball. Надо надеяться, кто-то может придумать лучший ответ.

0
27.01.2020, 19:48

Спасибо за проблему я придумал:

#!/bin/bash
#

# tarballs to check in
find authors/ -type f | while read tarball; do

    # get list of files in tarball (not dirs ending in /):
    tar tzf $tarball | grep -v '/$' | while read file; do       

        # get contents of file and look for string
        tar -Ozxf conform.tar.gz $file | grep -q 'Text::Version' && echo "Tar ($tarball) has matching File ($file)"

    done

done
0
27.01.2020, 19:48
  • 1
    Просто видел Ваше требование номера строки. Это может, вероятно, работать с некоторой комбинацией grep-n и awk для получения номера строки. Не может быть столь же простым как grep-H для списка имени файла, так как это всегда stdin, так мог бы потребовать большего количества строк. ошибки –  Kyle Smith 25.05.2011, 17:24
  • 2
    при выполнении в моей системе, бесконечной повторенный: tar (child): conform.tar.gz: Cannot open: No such file or directory tar (child): Error is not recoverable: exiting now tar: Child returned status 2 tar: Error is not recoverable: exiting now –  xenoterracide 25.05.2011, 17:43
  • 3
    также, который я не понял, когда я сначала отправил это, что некоторые архивы на cpan являются zip-файлами. –  xenoterracide 25.05.2011, 17:45
  • 4
    Гм, я протестировал со структурой только .tar.gz файлы - это могло быть сделано более устойчивым для принятия соответствующих мер на основе типа файла, но это должно дать достойную начальную точку. –  Kyle Smith 25.05.2011, 21:35

Возможно, мой ответ будет полезный для кого-то:

#!/bin/bash

findpath=$(echo $1 | sed -r 's|(.*[^/]$)|\1/|')

# tarballs to check in
find $findpath -type f | while read tarball; do

    # get list of files in tarball (not dirs ending in /):
    if [ -n "$(file --mime-type $tarball | grep -e "application/jar")" ]; then

        jar tf $tarball | grep -v '/$' | while read file; do
            # get contents of file and look for string
            grepout=$(unzip -q -c $tarball $file | grep $3 -e "$2")

            if [ -n "$grepout" ]; then
                echo "*** $tarball has matching file ($file):"
                echo $grepout
            fi

        done

    elif tar -tf $tarball 2>/dev/null; then

        tar -tf $tarball | grep -v '/$' | while read file; do
            # get contents of file and look for string
            grepout=$(unzip -q -c $tarball $file | grep $3 -e "$2")

            if [ -n "$grepout" ]; then
                echo "*** $tarball has matching file ($file):"
                echo $grepout
            fi

        done

    else
        file=""
        grepout=$(grep $3 -e "$2" $tarball)

        if [ -n "$grepout" ]; then
            echo "*** $tarball has matching:"
            echo $grepout
        fi

    fi

done
0
27.01.2020, 19:48

После установки p7zip-* вы можете сделать это:

ls | xargs -I {} 7z l {} | grep whatever | less

Вам не нужно использовать ls перед первым трубопроводом, какой бы список не работал в сжатых файлах. Последний минус покажет только PATH жизни списка внутри сжатого архива, но не имя этого.

0
27.01.2020, 19:48

Используйте find, чтобы найти все необходимые файлы, и этот zgrep для просмотра сжатых файлов:

find <folder> -type f -name "<search criteria[*gz,*bz...]>" -execdir zgrep -in "<grep expression>" '{}' ';'

Не тестировал это на tarballs, хотя

0
27.01.2020, 19:48

Теги

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