8

If you tar a directory recursively, it just uses the order from the os's readdir.

But in some cases it's nice to tar the files sorted.

What's a good way to tar a directory sorted alphabetically?


Note, for the purpose of this question, gnu-tar on a typical Linux system is fine.

16

For a GNU tar:

--sort=ORDER
 Specify the directory sorting order when reading directories.
 ORDER may be one of the following:

`none'
      No directory sorting is performed. This is the default.

`name'
      Sort the directory entries on name. The operating system may
      deliver directory entries in a more or less random order, and
      sorting them makes archive creation reproducible.

`inode'
      Sort the directory entries on inode number. Sorting
      directories on inode number may reduce the amount of disk
      seek operations when creating an archive for some file
      systems.

You'll probably also want to look at --preserve-order.

  • 5
    --sort was introduced in tar version 1.28. --preserve-order is not relevant to this question. – mhsmith Mar 3 '16 at 13:17
  • I am keep having tar: Exiting with failure status due to previous errors error. @mhsmith – alper Sep 30 '18 at 16:13
3

With zsh, instead of:

pax -w dir

Use:

pax -dw dir dir/**/*(D)

You can do the same with recent versions of bash -O globstar -O dotglob with:

pax -dw dir/**

Or recent versions of FIGNORE='@(.|..)' ksh93 -o globstar with:

pax -dw dir dir/**

pax is the standard command to make tar files. The output goes to stdout. Shell globs are sorted by name.

If you run into an Arg list too long error, you can change to:

printf '%s\0' dir dir/**/*(D) | pax -0dw

(not all pax implementations support -0 though).

2

tar itself cannot do this, so you have to create it from a correctly ordered list. In principle you could then use tar's -T option, but there is no way to specify that the filenames in that list should be NUL terminated. So if you have any filenames with newlines in them (which is allowed) this will just break.

A better option is to use cpio to generate the files as that accepts a NUL terminated list of filenames and can generate tar files.

If your tar command would be:

tar cvf /somedir/all.tar .

Then for this to be sorted by name you would have to do (assuming GNU find and cpio):

find . -type f -print0 | sort -z | \
  cpio --create --null --format=ustar -O /somedir/all.tar

This has the disadvantage though that subdirectories are placed in between filenames. You can do tricks with finds -printf0 specifying the directory and depth information and sorting with sort -n but that also influences how files with numbers are sorted within a directory.

If the above is not satisfactory you could probably use a small python program based on os.walk() to generate the ordering you want with full control (depth first, based on extenion etc), but if you go that route you might as well drop cpio and write out the tar file with python's tarfile module.

  • 1
    --null specifies that -T takes null terminated strings. – psusi Jan 8 '15 at 15:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.