libarchiveè in bsdtargrado di gestire la maggior parte di quei formati di file, quindi puoi fare:
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
Che puoi semplificare (e migliorare per far corrispondere maiuscole e minuscole) con GNU findcon:
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
Ciò non stampa il percorso dell'archivio in cui *vacation*jpgsi trovano quei file. Per stampare quel nome è possibile sostituire l'ultima riga con:
-exec sh -ac '
for ARCHIVE do
bsdtar tf "$ARCHIVE" "*vacation*jpg" |
awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
done' sh {} + 2> /dev/null
che fornisce un output come:
./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
}
Nota che ci sono un certo numero di altri formati di file che sono giusti zipo tgzfile sotto mentite spoglie .jaro .docxfile. Puoi aggiungerli al tuo modello find/ zshsearch, bsdtarnon importa l'estensione (come in, non si basa sull'estensione per determinare il tipo di file).
Si noti che *vacation*.jpgsopra corrisponde al percorso completo del membro dell'archivio, non solo al nome del file, quindi corrisponderebbe a vacation.jpgma anche a vacation/2014/file.jpg.
Per abbinare solo il nome del file, un trucco sarebbe usare la modalità di estrazione , usare -s(sostituzione) che usa regexps con un pflag per stampare i nomi dei file corrispondenti e quindi assicurarsi che nessun file sia estratto, come:
bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"
Notare che avrebbe generato l'elenco su stderr e aggiunto >>a ogni riga. In ogni caso, bsdtarcome la maggior parte delle tarimplementazioni possono alterare i nomi dei file visualizzati se contengono alcuni caratteri come newline o barra rovesciata (renderizzati come \no \\).