I've received a Unix software distribution as a compressed cpio file. What's the best command to extract the files?
5 Answers
gzip -cd foo.cpio.gz | cpio -idmv
- i : extract (input)
- d : create directories
- m : preserve mtime
- v : verbose
- 1,092
mkdir archive
cd archive
zcat ../archive.cpio.gz | cpio -idmv --no-absolute-filenames
While this is an old question, it shows up high on Google, so I thought I might update it. I agree with the accepted answer in general, but you should add "--no-absolute-filenames" unless you are intending to overwrite important system files on your machine. Also, personally, I prefer "zcat" over "gzip -cd" or "gunzip -c".
Finally, note that you need to run cpio as root (e.g. sudo) if you are extracting a root filesystem that contains device nodes.
- 183
- 1
- 4
As shown in https://linuxconfig.org/how-to-uncompress-and-list-an-initramfs-content-on-linux, a cpio archive can consist of multiple parts with even different compression, so cpio -idmv is no guarantee at all to extract all files contained in the archive.
Of a test file of 79M on my system, only 60KB were extracted.
Unfortunately, compression itself is not part of cpio, so multiple tricks must be done, including calculating offsets and using dd.
The tool unmkinitramfs (apt-get install initramfs-tools-core) should cover all use cases that also the kernel is aware of:
unmkinitramfs /my/initrd.img /extract/path/
But also here, please note the warning in the man page:
BUGS
unmkinitramfs cannot deal with multiple-segmented initramfs images, except where an early (uncompressed) initramfs with system firmware is prepended to the regular compressed initramfs.
here is a full manual example process using cpio and dd:
Each step contains file for discovering the compression format, then uncomprompressing if necessary and unpacking. Starting with the second step, I use dd and calculate the offset (output of previous cpio command plus previously used offset).
part one (uncompressed)
$ cat /tmp/initrd.img | file -
/dev/stdin: ASCII cpio archive (SVR4 with no CRC)
$ cat /tmp/initrd.img | cpio -idmv
.
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/AuthenticAMD.bin
151 blocks
part two (uncompressed)
$ dd skip=151 if=/tmp/initrd.img | file -
/dev/stdin: ASCII cpio archive (SVR4 with no CRC)
$ dd skip=151 if=/tmp/initrd.img | cpio -idmv
kernel
kernel/x86
kernel/x86/microcode
kernel/x86/microcode/GenuineIntel.bin
15586 blocks
part three (compressed)
$ dd skip=$((151+15586)) if=/tmp/initrd.img | file -
/dev/stdin: XZ compressed data, checksum CRC32
$ dd skip=$((151+15586)) if=/tmp/initrd.img | xz -d | file -
/dev/stdin: ASCII cpio archive (SVR4 with no CRC)
$ dd skip=$((151+15586)) if=/tmp/initrd.img | xz -d | cpio -idmv
[...lots of files]
var/lib
var/lib/dhcp
806862 blocks
part four (not existing - end of file, just to check)
$ dd skip=$((151+15586+806862)) if=/tmp/initrd.img | file -
dd: /tmp/initrd.img: cannot skip to specified offset
0+0 records in
0+0 records out
0 bytes copied, 7.5479e-05 s, 0.0 kB/s
/dev/stdin: empty
- 262
For example, to extract the archived contents of /etc/httpd/ to the current directory, creating subdirectories ./etc/httpd/
mkdir restored-etc-httpd
cd restored-etc-httpd
zcat archive.cpio.gz | cpio -idmv --no-absolute-filenames "*etc/httpd/*"
The accepted answer and Matt's were both helpful to me but I was stumped for a while because of three details:
- The matching pattern needs to be quoted to work as a pattern :P
- The option
--no-absolute-filenamesmust precede the pattern on the command line - Since that option removes the leading
/from filenames, the matching pattern must also omit the leading/
This Wikipedia page on cpio has some good notes.
For more details, refer to the cpio manual.
A link from the same Wikipedia page discusses comparison with tar archives.
And, here is an example of using cpio with the tar format.
- 57,042