libarchive
«s 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
search, bsdtar
не заботясь о расширении (например, он не использует расширение для определения типа файла).
Обратите внимание, что *vacation*.jpg
приведенное выше сопоставляется с полным путем к элементу архива, а не только с именем файла, поэтому он будет совпадать с включенным, vacation.jpg
но также и с включенным vacation/2014/file.jpg
.
Чтобы сопоставить только имя файла, можно использовать режим извлечения , использовать -s
(замену), который использует регулярные выражения с p
флагом для печати имен соответствующих файлов, а затем убедиться, что ни один файл не извлечен, например:
bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"
Обратите внимание, что он выведет список на stderr и добавит >>
к каждой строке. В любом случае, bsdtar
как и в большинстве tar
реализаций, могут отображаться имена файлов на дисплее, если они содержат некоторые символы, такие как символ новой строки или обратный слеш (отображается как \n
или \\
).