libarchive
's bsdtar
podem lidar com a maioria desses formatos de arquivo, assim que você poderia fazer:
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
Com o que você pode simplificar (e melhorar para corresponder a maiúsculas e minúsculas) com o 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
Isso não imprime o caminho do arquivo onde esses *vacation*jpg
arquivos são encontrados. Para imprimir esse nome, você pode substituir a última linha por:
-exec sh -ac '
for ARCHIVE do
bsdtar tf "$ARCHIVE" "*vacation*jpg" |
awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
done' sh {} + 2> /dev/null
que fornece uma saída como:
./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
Ou com 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
}
Note-se que há uma série de outros formatos de arquivo que são apenas zip
ou tgz
arquivos disfarçados como .jar
ou .docx
arquivos. Você pode adicioná-los ao seu padrão find
/ zsh
pesquisa, bsdtar
não se importa com a extensão (como em, ele não depende da extensão para determinar o tipo do arquivo).
Observe que *vacation*.jpg
acima é correspondido no caminho completo do membro do arquivamento, não apenas no nome do arquivo; portanto, ele corresponderá, vacation.jpg
mas também ativará vacation/2014/file.jpg
.
Para corresponder apenas ao nome do arquivo, um truque seria usar o modo de extração , use -s
(substituição) que usa regexps com um p
sinalizador para imprimir os nomes dos arquivos correspondentes e, em seguida, verifique se nenhum arquivo foi extraído, como:
bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"
Note que ele produziria a lista no stderr e acrescentaria >>
a cada linha. De qualquer forma ,, bsdtar
como a maioria das tar
implementações, os nomes dos arquivos são mostrados se eles contiverem caracteres como nova linha ou barra invertida (renderizada como \n
ou \\
).