]> git.ipfire.org Git - thirdparty/tar.git/blame - doc/recipes.texi
Avoid quadratic behavior with delayed links
[thirdparty/tar.git] / doc / recipes.texi
CommitLineData
9855bc01 1@c This is part of the GNU tar manual.
5c713540 2@c Copyright (C) 2017--2022 Free Software Foundation, Inc.
9855bc01
SP
3@c This file is distributed under GFDL 1.3 or any later version
4@c published by the Free Software Foundation.
5
6This appendix provides several recipes for performing common tasks
7using @GNUTAR{}.
8
9@menu
10* copy directory hierarchy::
11* intermediate directories::
12@end menu
13
14@node copy directory hierarchy
15@appendixsec Copying directory hierarchies
16
17This is a traditional way to copy a directory hierarchy preserving
18the dates, modes, owners and link-structure of all the files therein.
19It was used back when the @command{cp} command lacked the @option{-a}
20option:
21
22@smallexample
23$ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xf -)}
24@end smallexample
25
26@noindent
27You can avoid subshells by using @option{-C} option:
28
29@smallexample
30$ @kbd{tar -C sourcedir -cf - . | tar -C targetdir -xf -}
31@end smallexample
32
33@noindent
34The same command using long option forms:
35
36@smallexample
37@group
38$ @kbd{(cd sourcedir; tar --create --file=- . ) \
39 | (cd targetdir; tar --extract --file=-)}
40@end group
41@end smallexample
42
43@noindent
44or
45
46@smallexample
47@group
48$ @kbd{tar --directory sourcedir --create --file=- . \
49 | tar --directory targetdir --extract --file=-}
50@end group
51@end smallexample
52
53@node intermediate directories
54@appendixsec Restoring Intermediate Directories
55
56A common concern is how to extract permissions and ownerships of
57intermediate directories when extracting only selected members from
58the archive. To illustrate this, consider the following archive:
59
60@example
61@group
62# tar tvf A.tar
63drwxr-xr-x root/root 0 2017-11-16 14:39 foo/
64dr-xr-x--- gray/user 0 2017-11-16 14:39 foo/bar/
65-rw-r--r-- gray/user 10 2017-11-16 14:40 foo/bar/file
66@end group
67@end example
68
69Suppose you extract only the file @file{foo/bar/file}, while being
70@samp{root}:
71
72@example
73# @kbd{tar xvf A.tar foo/bar/file}
74foo/bar/file
75@end example
76
77Now, let's inspect the content of the created directories:
78
79@example
80@group
81# find foo -ls
82427257 0 drwxr-xr-x 3 root root 16 Nov 17 16:10 foo
83427258 0 drwxr-xr-x 2 root root 17 Nov 17 16:10 foo/bar
84427259 0 -rw-r--r-- 1 gray user 10 Nov 6 14:40 foo/bar/file
85@end group
86@end example
87
88The requested file is restored, including its ownership and
89permissions. The intermediate directories, however, are created with
90the default permissions, current timestamp and owned by the current
91user. This is because by the time @command{tar} has reached the requested file,
92it had already skipped the entries for its parent directories, so it
93has no iformation about their ownership and modes.
94
95To restore meta information about the intermediate directories,
96you'll need to specify them explicitly in the command line and use the
97@option{--no-recursive} option (@pxref{recurse}) to avoid extracting
98their content.
99
100To automate this process, @cite{Neal P. Murphy} proposed the following
101shell script@footnote{The original version of the script can be
102seen at @uref{http://lists.gnu.org/archive/html/bug-tar/2016-11/msg00024.html}}:
103
104@example
105@group
106#! /bin/sh
107(while read path
108 do
109 path=`dirname $path`
110 while [ -n "$path" -a "$path" != "." ]
111 do
112 echo $path
113 path=`dirname $path`
114 done
115 done < $2 | sort | uniq) |
116 tar -x --no-recursion -v -f $1 -T - -T $2
117@end group
118@end example
119
120The script takes two arguments: the name of the archive file, and the
121name of the file list file.
122
123To complete our example, the file list will contain single line:
124
125@example
126foo/bar/file
127@end example
128
129Supposing its name is @file{file.list} and the script is named
130@file{restore.sh}, you can invoke it as follows:
131
132@example
133# @kbd{sh restore.sh A.tar file.list}
134@end example