Строки, добавленные автоматической функцией конфигурирования, отмечены в Вашем ~/.zshrc
:
# Lines configured by zsh-newuser-install
…
# End of lines configured by zsh-newuser-install
Пока Вы не редактируете эти строки или что-либо промежуточное, можно продолжать использовать интерфейс конфигурирования, и это отредактирует строки между этими маркерами. Добавьте, что Вы хотите прежде или после маркеров. Обычно Вы будете хотеть, чтобы Ваш материал следовал за маркером конца, так, чтобы он не был переопределен настройками от интерфейса конфигурирования.
(Адаптированный от того, Как делают меня рекурсивно grep через сжатые архивы?)
Установите AVFS, файловая система, которая обеспечивает прозрачный доступ в архивах. Первый показ эта команда однажды для установки представления файловой системы машины, в которой можно получить доступ к архивам, как будто они были каталогами:
mountavfs
После этого если /path/to/archive.zip
признанный архив, затем ~/.avfs/path/to/archive.zip#
каталог, который, кажется, содержит содержание архива.
find ~/.avfs"$PWD" \( -name '*.7z' -o -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
-exec sh -c '
find "$0#" -name "*vacation*.jpg"
' {} 'Test::Version' \;
Объяснения:
~/.avfs$PWD
, который является представлением AVFS текущего каталога.$0
= заархивируйте имя и $1
= шаблон для поиска).$0#
представление каталога архива $0
.{\}
вместо {}
необходим в случае, если внешнее find
замены {}
внутри -exec ;
аргументы (некоторые делают это, некоторые не делают).Или в zsh ≥4.3:
mountavfs
ls -l ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|zip)(e\''
reply=($REPLY\#/**/*vacation*.jpg(.N))
'\')
Объяснения:
~/.avfs$PWD/**/*.(7z|tgz|tar.gz|zip)
соответствия архивируют в представлении AVFS текущего каталога и его подкаталогов.PATTERN(e\''CODE'\')
применяет КОД к каждому соответствию ШАБЛОНА. Название подобранного файла находится в $REPLY
. Установка reply
массив превращает соответствие в список имен.$REPLY\#
представление каталога архива.$REPLY\#/**/*vacation*.jpg
соответствия *vacation*.jpg
файлы в архиве.N
спецификатор шарика заставляет шаблон расшириться до пустого списка, если там не идет ни в какое сравнение.Если Вы хотите что-то более простое, что решение AVFS, я записал, что сценарий Python, чтобы сделать это назвал arkfind. Можно на самом деле просто сделать
$ arkfind /path/to/search/ -g "*vacation*jpg"
Это сделает это рекурсивно, таким образом, можно будет посмотреть на архивы в архивах к произвольной глубине.
Мое обычное решение:
find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|DESIRED_FILE_TO_SEARCH'
Пример:
find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|characterize.txt'
Результат примерно такой:
foozip1.zip:
foozip2.zip:
foozip3.zip:
DESIRED_FILE_TO_SEARCH
foozip4.zip:
...
Если вы хотите только zip-файл с попадает в :
find -iname '*.zip' -exec unzip -l {} \; 2>/dev/null | grep '\.zip\|FILENAME' | grep -B1 'FILENAME'
FILENAME здесь используется дважды, поэтому вы можете использовать переменную.
С find вы можете использовать ПУТЬ / К / ПОИСК
ИМХО удобство для пользователя должно быть частью bash:
while read -r zip_file ; do echo "$zip_file" ; unzip -l "$zip_file" | \
grep -i --color=always -R "$to_srch"; \
done < <(find . \( -name '*.7z' -o -name '*.zip' \)) | \
less -R
и tar (этот не тестировался. ..)
while read -r tar_file ; do echo "$tar_file" ; tar -tf "$tar_file" | \
grep -i --color=always -R "$to_srch"; \
done < <(find . \( -name '*.tar.gz' -o -name '*.tar' \)) | \
less -R
libarchive
bsdtar
может обрабатывать большинство этих форматов файлов, поэтому вы можете:
find . \( -name '*.zip' -o \
-name '*.tar' -o \
-name '*.tar.gz' -o \
-name '*.tar.bz2' -o \
-name '*.tar.xz' -o \
-name '*.tgz' -o \
-name '*.tbz2' -o \
-name '*.7z' -o \
-name '*.iso' -o \
-name '*.cpio' -o \
-name '*.a' -o \
-name '*.ar' \) \
-type f \
-exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null
Что вы можете упростить ( и улучшите соответствие без учета регистра) с помощью GNU find
с помощью:
find . -regextype egrep \
-iregex '.*\.(zip|7z|iso|cpio|ar?|tar(|\.[gx]z|\.bz2)|tgz|tbz2)' \
-type f \
-exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null
Это не печатает путь к архиву, в котором находятся файлы * vacation * jpg
. Чтобы напечатать это имя, вы можете заменить последнюю строку на:
-exec sh -ac '
for ARCHIVE do
bsdtar tf "$ARCHIVE" "*vacation*jpg" |
awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
done' sh {} + 2> /dev/null
, что даст следующий результат:
./a.zip: foo/blah_vacation.jpg
./a.zip: bar/blih_vacation.jpg
./a.tar.gz: foo/blah_vacation.jpg
./a.tar.gz: bar/blih_vacation.jpg
Или на zsh
:
setopt extendedglob # best in ~/.zshrc
for archive (**/*.(#i)(zip|7z|iso|cpio|a|ar|tar(|.gz|.xz|.bz2)|tgz|tbz2)(.ND)) {
matches=("${(f@)$(bsdtar tf $archive '*vacation*jpg' 2> /dev/null)"})
(($#matches)) && printf '%s\n' "$archive: "$^matches
}
Обратите внимание, что существует ряд других форматов файлов, которые просто zip
или tgz
файлы, замаскированные, например файлы .jar
или .docx
. Вы можете добавить их в свой шаблон поиска find
/ zsh
, bsdtar
не заботится о расширении (например, он не полагается на расширение для определения типа файла).
Обратите внимание, что * vacation * .jpg
выше соответствует полному пути к члену архива, а не только имени файла, поэтому он будет совпадать с vacation.jpg
, но также и с отпуск / 2014 / file.jpg
.
Чтобы сопоставить только имя файла, можно использовать режим extract , использовать -s
(подстановка), который использует регулярные выражения с p
флаг, чтобы напечатать имена совпадающих файлов, а затем убедиться, что файл не извлечен, например:
bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"
Обратите внимание, что он выводит список на stderr и добавляет >>
в каждую строку. В любом случае bsdtar
, как и большинство реализаций tar
, может искажать имена файлов на дисплее, если они содержат некоторые символы, такие как новая строка или обратная косая черта (отображаемые как \ n
или \
).