Home / Alt manpages / cpio(1)

  • cpio(1)
  • User command
  • linux

Build and Inspect cpio Archives without Clobbering Files

This guide builds a GNU cpio archive, inspects it before extraction, and unpacks it into a controlled directory of its own. These examples use GNU cpio 2.15, installed here as package version 2.15+dfsg-1ubuntu2.1. Allow about fifteen minutes, plus whatever time it takes to decide which files actually belong in the archive.

You need a shell, the cpio package, a readable source directory and enough space for both the archive and its extracted copy. Every example here is an ordinary user command; reach for sudo only when the files or destination genuinely need elevated access.

1. Check the installed command

Confirm which executable will actually run and record its version:

$ command -v cpio
/usr/bin/cpio
$ cpio --version
cpio (GNU cpio) 2.15
...

This guide follows the GNU command as documented by the local manual page. The operation mode is never inferred from the archive name: pick copy-out with -o, copy-in with -i, or pass-through with -p.

2. Create an archive from a deliberate file list

Move into the directory whose relative paths you want stored. Feeding cpio a list from find keeps the selection visible and stops you accidentally archiving the archive itself:

$ cd /path/to/source
$ find project -type f -print > /tmp/project-files.txt
$ cpio -o -H newc -F /path/to/project.cpio < /tmp/project-files.txt
42 blocks

-o reads names from standard input and writes the archive; -F names the archive file, while -H newc picks the SVR4 format GNU cpio supports. That block count is just normal completion output, not a file listing. The archive now holds names relative to /path/to/source, such as project/config.ini.

Checkpoint: confirm the archive exists and is not empty before you do anything at all to the source:

$ ls -lh /path/to/project.cpio
$ test -s /path/to/project.cpio && echo 'archive is non-empty'
archive is non-empty

3. Make file lists safe for unusual names

The default input delimiter is a newline, which falls over for any filename that itself contains a newline, and plain shell pipelines get hard to audit once names contain spaces too. Use null delimiters when you build an archive straight from find:

$ cd /path/to/source
$ find project -type f -print0 | cpio --null --create --format=newc --file=/path/to/project.cpio
42 blocks

The matching options are --null on the cpio side and -print0 on GNU find's. Keep the input list and the working directory aligned: run find from the wrong directory and the archive can still look valid while holding paths you never intended.

Symbolic links are stored as links by default. Adding --dereference follows them instead and stores the files they point to, which can pull in data from well outside the source tree. Treat that option as a deliberate boundary change, not a minor tweak.

4. Inspect before extracting

Read the archive's table of contents without writing a single file:

$ cpio --list --verbose --file=/path/to/project.cpio
-rw-r--r--   1 alice    alice        1842 Sep 22 20:10 project/config.ini
-rw-r--r--   1 alice    alice       30112 Sep 22 20:10 project/README.md
42 blocks

-t implies copy-in mode, and -v prints each entry. Look for unexpected absolute paths, parent-directory components such as ../, device files, or anything that would overwrite data you care about. A listing is an inspection step, not proof that extraction is harmless: ownership, permissions and links can still change the outcome.

To inspect just a subset, add a pattern after the options:

$ cpio -itv -F /path/to/project.cpio 'project/*.conf'
-rw-r--r--   1 alice    alice         210 Sep 22 20:10 project/app.conf
1 block

Quote shell wildcards so the shell does not expand them against the current directory before cpio ever sees them.

5. Extract into a fresh destination

Never test an unfamiliar archive directly inside a live configuration directory. Create an empty destination first, then extract there:

$ install -d /tmp/cpio-review
$ cpio --extract --make-directories --verbose --file=/path/to/project.cpio -D /tmp/cpio-review
project/config.ini
project/README.md
42 blocks
$ find /tmp/cpio-review -type f -print
/tmp/cpio-review/project/config.ini
/tmp/cpio-review/project/README.md

--make-directories creates any leading directories needed; -D changes into the destination before processing the archive. The local manual says absolute filenames are the default, so add --no-absolute-filenames when you want extracted files forced relative to the destination instead. That is a useful extra guard, but review the listing first regardless.

Extraction only overwrites an existing file when you request unconditional replacement with -u, though the absence of -u is not a complete safety mechanism on its own: a destination can already hold files, and metadata or links still deserve a look.

6. Verify and recover

Compare the extracted files against the source with a read-only check:

$ diff -ruN /path/to/source/project /tmp/cpio-review/project
$ cmp /path/to/source/project/README.md /tmp/cpio-review/project/README.md && echo identical
identical

A clean diff produces no output at all. Keep the source and original archive intact until this check passes. If extraction left behind an unwanted review tree, remove only that known temporary directory:

$ rm -rf /tmp/cpio-review

That removal cannot be undone for anything inside it. If you extracted into a real destination by mistake, stop writing to it immediately, note what changed, and restore from that destination's backup or version-control history: cpio has no transaction or undo command of its own.

On failure, GNU cpio exits with status 2. Capture it right away if a script needs to tell success from failure:

$ cpio -it -F /path/to/project.cpio >/tmp/cpio-list.txt
$ status=$?
$ printf 'cpio exit status: %s\n' "$status"
cpio exit status: 0

Do not mistake the block count for a verification result. Check the exit status and look at the actual files you care about.

Done means

  • The installed program is GNU cpio 2.15, or a version whose manual you have checked.
  • The archive came from a reviewed file list, with null delimiters so unusual filenames survive automated input.
  • The table of contents was inspected before extraction happened.
  • Extraction landed in a controlled destination, never over a live system tree.
  • The extracted files were checked, and the original source and archive were kept until verification finished.