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
您可以find
通过以下方式使用GNU简化(并提高以区分大小写的方式匹配):
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
也可以匹配vacation/2014/file.jpg
。
要仅匹配文件名,一种技巧是使用提取模式,使用-s
(替换),它使用带有p
标志的regexps 打印匹配文件的名称,然后确保未提取文件,例如:
bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"
请注意,它将在stderr上输出列表并追加>>
到每一行。无论如何,bsdtar
像大多数tar
实现一样,如果它们包含换行符或反斜杠(呈现为\n
或\\
)之类的字符,则它们可能会破坏显示的文件名。