Extract only a specific file from a zipped archive to a given directory
I need to extract a single file from a ZIP file which I know the path to. Is there a command like the following:
unzip -d . myarchive.zip path/to/zipped/file.txt
Unfortunately, the above command extracts and recreates the entire path to the file at ./path/to/zipped/file.txt
. Is there a way for me to simply pull the file out into a specified directory?
You can extract just the text to standard output with the -p
option:
unzip -p myarchive.zip path/to/zipped/file.txt >file.txt
This won’t extract the metadata (date, permissions, …), only the file contents (obviously, it only works for regular files, not symlinks, devices, directories…). That’s the price to pay for the convenience of not having to move the file afterwards.
Alternatively, mount the archive as a directory and just copy the file. With AVFS:
mountavfs
cp -p ~/.avfs"$PWD/myarchive.zip#"/path/to/zipped/file.txt .
Or with fuse-zip:
mkdir myarchive.d
fuse-zip myarchive.zip myarchive.d
cp -p myarchive.d/path/to/zipped/file.txt .
fusermount -u myarchive.d; rmdir myarchive.d
unzip -j "myarchive.zip" "in/archive/file.txt" -d "/path/to/unzip/to"
Enter full path for zipped file, not just the filename. Be sure to keep the structure as seen from within the zip file.
This will extract the single file file.txt
in myarchive.zip
to /path/to/unzip/to/file.txt
.
-j
: junk paths. The archive’s directory structure is not recreated; all files are deposited in the extraction directory (by default, the current one)
-d
: An optional directory to which to extract files.
https://www.mankier.com/1/unzip
Multiple files:
unzip -j myarchive.zip in/archive/file.txt another/file.ext -d /path/to/unzip/to
Entire Sub-directory
unzip -j archive.zip "sub/dir/*" -d "dest/dir"
Simpler version:
unzip ARCHIVE_NAME PATH_OF_FILE_INSIDE_ARCHIVE
This will recreate PATH_OF_FILE_INSIDE_ARCHIVE
in current directory but only extracts specified file.
To list all files in a Zip archive:
unzip -l ARCHIVE_NAME
On macOS, which by default uses Info-Zip
First list off the files to find what you want
unzip -l my.zip
Then extract file from the archive
unzip my.zip annoying/path/to/file/in/zip
Combine with -p for stdout
unzip -p my.zip annoying/path/to/file/in/zip >./file
or -j for extracting to the current directory (discard junk path)
unzip -j my.zip annoying/path/to/file/in/zip
with -d you can specify to create an arbitrary directory
unzip -d /path/to/dir my.zip annoying/path/to/file/in/zip
If you want the file in the -d
directory you probably want to combine it with the -j
option.
simple use:
unzip zipfile.zip path/inside/zip/file.txt
and it will inflate the file.
$ unzip -l ./../html.zip | grep wp-config
3328 07-22-2019 15:10 html/wp-config.php
2898 01-07-2019 23:30 html/wp-config-sample.php
$ unzip ./../html.zip html/wp-config.php
Archive: ./../html.zip
inflating: html/wp-config.php
$ ls -lrth
total 4.0K
drwxr-sr-x 2 apache apache 4.0K Jul 26 14:41 html
$ ls -lrth html/*
total 4.0K
-rw-rw-rw- 1 apache apache 3.3K Jul 22 15:10 wp-config.php
Extract to a relative dir
unzip -j -d relativedir archive.zip path/in/archive/file.ext
Extract to the current dir
unzip -j -d . archive.zip path/in/archive/file.ext
Extract to absolute dir
unzip -j -d /absolutedir archive.zip path/in/archive/file.ext
If you want to restore the file’s metadata from the archive, be able to restore files of any type (including symlinks) and with arbitrary names, and also choose the new name of the file, you could use libarchive’s bsdtar
(which also supports ZIP format archives) instead of unzip
as:
bsdtar -nqvvxpf file.zip -'s/.*/newname/S' some/dir/originalname
Note: like in unzip
, the some/dir/originalname
there is taken as a shell wildcard pattern. So if the path of archive member you want to extract does contain *
, ?
, or
[
characters, you’ll need to escape them as in:
bsdtar -nqvvxpf file.zip -'s/.*/newname/S' 'som[?]/dir/[*]riginalname'
or:
bsdtar -nqvvxpf file.zip -'s/.*/newname/S' 'som?/dir/*riginalname'
if the archive member is called som?/dir/*riginalname
.
Note that that approach would work with any of the archive formats supported by libarchive, not just zip.
unzip myarchive.zip `zipinfo -2 myarchive.zip | head -1`