libarchive
's bsdtar
puede manejar la mayoría de esos formatos de archivo, por lo que podría hacer:
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
Que puede simplificar (y mejorar para que coincida entre mayúsculas y minúsculas) con GNU find
con:
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
Sin embargo, eso no imprime la ruta del archivo donde *vacation*jpg
se encuentran esos archivos. Para imprimir ese nombre, puede reemplazar la última línea con:
-exec sh -ac '
for ARCHIVE do
bsdtar tf "$ARCHIVE" "*vacation*jpg" |
awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
done' sh {} + 2> /dev/null
que da una salida 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
O con 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
}
Tenga en cuenta que hay varios otros formatos de archivo que son justos zip
o tgz
archivos disfrazados como .jar
o .docx
archivos. Puede agregarlos a su patrón find
/ zsh
search, bsdtar
no le importa la extensión (como en, no depende de la extensión para determinar el tipo de archivo).
Tenga en cuenta que lo *vacation*.jpg
anterior coincide con la ruta completa del miembro de archivo, no solo con el nombre del archivo, por lo que coincidiría con, vacation.jpg
pero también con vacation/2014/file.jpg
.
Para hacer coincidir solo el nombre del archivo, un truco sería usar el modo de extracción , usar -s
(sustitución) que usa expresiones regulares con una p
bandera para imprimir los nombres de los archivos coincidentes y luego asegurarse de que no se extraiga ningún archivo, como:
bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"
Tenga en cuenta que generará la lista en stderr y se agregará >>
a cada línea. En cualquier caso, bsdtar
como la mayoría de las tar
implementaciones, pueden alterar los nombres de los archivos que se muestran si contienen algunos caracteres como nueva línea o barra diagonal inversa (representados como \n
o \\
).