277

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?

8 Answers 8

252

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
5
  • 1
    Will it work for binary files, say a jar file? Jun 1, 2011 at 1:01
  • 1
    @TKKocheran: Jar files are zips, so the unzip and fuse-zip methods will obviously work. The AVFS method also works, because AVFS guesses the format based on file names and knows about .jar; if your file is named differently you might need to tell AVFS to use its zip handler, e.g. ~/.avfs$PWD/foo.apk#uzip/META-INF. Jun 1, 2011 at 7:19
  • 1
    actually, I meant extracting a JAR/binary file from a ZIP archive. I haven't had the chance to test it out yet, can you see any issues using the first command above to extract binary files? Jun 1, 2011 at 18:41
  • 2
    @TKKocheran: There's no problem, -p extracts the file as-is (-c does text conversion). Jun 1, 2011 at 20:50
  • 3
    I think the answer of @Myles is more elegant, because it doesn't require output redirection and it preserves file attributes.
    – gertvdijk
    Dec 4, 2012 at 15:42
238
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"
8
  • 2
    It doesn't handle the case where you want the generated filename to be different. Oct 27, 2014 at 21:21
  • 11
    the "-j" paramter: junk paths. The archive's directory structure is not recreated; all files are deposited in the extraction directory (by default, the current one). the "-d" parameter: extract files into exdir
    – e1i45
    Jan 29, 2015 at 16:14
  • 2
    @OlegVaskevich, the question doesn't request target filename to be different
    – Tapemaster
    May 11, 2015 at 10:49
  • 1
    FYI to find out the path of files in zip, use less: superuser.com/questions/216617/…
    – Yibo Yang
    Oct 24, 2017 at 6:17
  • 4
    unzip accepts wildcard, so to unzip sub-directory: unzip -j archive.zip "sub/dir/*" -d "dest/dir"
    – Noam Manos
    May 21, 2020 at 10:27
53

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
2
  • This works with wildcards too, at least in CentOS - e.g. unzip foo.zip *.bar
    – aland
    May 21, 2020 at 14:32
  • 1
    this is all i needed. very succinct. don't really see any benefit in using other methods unless you need to extract many files at once. Aug 17, 2021 at 1:59
15

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.

0
5

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
2
  • 1
    Can also add the -d outpath argument to specify where the file is put in.
    – Efren
    Sep 18, 2019 at 2:45
  • 1
    And the -j argument to avoid the compressed paths
    – Efren
    Sep 18, 2019 at 2:56
1

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.

0

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
-1
unzip myarchive.zip `zipinfo -2 myarchive.zip | head -1`
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .