Tar archives contain detailed information about files stored in them and full file names are part of that information. When storing a file to an archive, its file name is recorded in it, along with the actual file contents. When restoring from an archive, a file is created on disk with exactly the same name as that stored in the archive. In the majority of cases this is the desired behavior of a file archiver. However, there are some cases when it is not.
First of all, it is often unsafe to extract archive members with absolute file names or those that begin with a ../. GNU tar takes special precautions when extracting such names and provides a special option for handling them, which is described in absolute.
Secondly, you may wish to extract file names without some leading directory components, or with otherwise modified names. In other cases it is desirable to store files under differing names in the archive.
GNU tar provides several options for these needs.
For example, suppose you have archived whole /usr hierarchy to a tar archive named usr.tar. Among other files, this archive contains usr/include/stdlib.h, which you wish to extract to the current working directory. To do so, you type:
$ tar -xf usr.tar --strip=2 usr/include/stdlib.h
The option --strip=2 instructs tar to strip the two leading components (usr/ and include/) off the file name.
If you add the --verbose (-v) option to the invocation above, you will note that the verbose listing still contains the full file name, with the two removed components still in place. This can be inconvenient, so tar provides a special option for altering this behavior:
For example:
$ tar -xf usr.tar -v --strip=2 usr/include/stdlib.h usr/include/stdlib.h $ tar -xf usr.tar -v --strip=2 --show-transformed usr/include/stdlib.h stdlib.h
Notice that in both cases the file stdlib.h is extracted to the current working directory, --show-transformed-names affects only the way its name is displayed.
This option is especially useful for verifying whether the invocation will have the desired effect. Thus, before running
$ tar -x --strip=n
it is often advisable to run
$ tar -t -v --show-transformed --strip=n
to make sure the command will produce the intended results.
In case you need to apply more complex modifications to the file name, GNU tar provides a general-purpose transformation option:
The expression is a sed-like replace expression of the form:
s/regexp/replace/[flags]
where regexp is a regular expression, replace is a replacement for each file name part that matches regexp. Both regexp and replace are described in detail in The "s" Command.
Any delimiter can be used in lieu of ‘/’, the only requirement being that it be used consistently throughout the expression. For example, the following two expressions are equivalent:
s/one/two/ s,one,two,
Changing delimiters is often useful when the regex contains
slashes. For example, it is more convenient to write s,/,-,
than
s/\//-/
.
As in sed, you can give several replace expressions, separated by a semicolon.
Supported flags are:
Note: the POSIX standard does not specify what should happen when you mix the ‘g’ and number modifiers. GNU tar follows the GNU sed implementation in this regard, so the interaction is defined to be: ignore matches before the numberth, and then match and replace all matches from the numberth on.
In addition, several transformation scope flags are supported, that control to what files transformations apply. These are:
Default is ‘rsh’, which means to apply tranformations to both archive members and targets of symbolic and hard links.
Default scope flags can also be changed using ‘flags=’ statement in the transform expression. The flags set this way remain in force until next ‘flags=’ statement or end of expression, whichever occurs first. For example:
--transform 'flags=S;s|^|/usr/local/|'
Here are several examples of --transform usage:
$ tar --transform='s,usr/,usr/local/,' -x -f arch.tar
$ tar --transform='s,/*[^/]*/[^/]*/,,' -x -f arch.tar
$ tar --transform 's/.*/\L&/' -x -f arch.tar
$ tar --transform 's,^,/prefix/,' -x -f arch.tar
$ tar --transform 's,^,/usr/local/,S' -c -f arch.tar /lib
Notice the use of flags in the last example. The /lib directory often contains many symbolic links to files within it. It may look, for example, like this:
$ ls -l drwxr-xr-x root/root 0 2008-07-08 16:20 /lib/ -rwxr-xr-x root/root 1250840 2008-05-25 07:44 /lib/libc-2.3.2.so lrwxrwxrwx root/root 0 2008-06-24 17:12 /lib/libc.so.6 -> libc-2.3.2.so ...
Using the expression ‘s,^,/usr/local/,’ would mean adding ‘/usr/local’ to both regular archive members and to link targets. In this case, /lib/libc.so.6 would become:
/usr/local/lib/libc.so.6 -> /usr/local/libc-2.3.2.so
This is definitely not desired. To avoid this, the ‘S’ flag is used, which excludes symbolic link targets from filename transformations. The result is:
$ tar --transform 's,^,/usr/local/,S', -c -v -f arch.tar \ --show-transformed /lib drwxr-xr-x root/root 0 2008-07-08 16:20 /usr/local/lib/ -rwxr-xr-x root/root 1250840 2008-05-25 07:44 /usr/local/lib/libc-2.3.2.so lrwxrwxrwx root/root 0 2008-06-24 17:12 /usr/local/lib/libc.so.6 \ -> libc-2.3.2.so
Unlike --strip-components, --transform can be used in any GNU tar operation mode. For example, the following command adds files to the archive while replacing the leading usr/ component with var/:
$ tar -cf arch.tar --transform='s,^usr/,var/,' /
To test --transform effect we suggest using --show-transformed-names option:
$ tar -cf arch.tar --transform='s,^usr/,var/,' \ --verbose --show-transformed-names /
If both --strip-components and --transform are used together, then --transform is applied first, and the required number of components is then stripped from its result.
You can use as many --transform options in a single command line as you want. The specified expressions will then be applied in order of their appearance. For example, the following two invocations are equivalent:
$ tar -cf arch.tar --transform='s,/usr/var,/var/' \ --transform='s,/usr/local,/usr/,' $ tar -cf arch.tar \ --transform='s,/usr/var,/var/;s,/usr/local,/usr/,'