Use stdopen from gnulib
[tar.git] / doc / recipes.texi
blob4310192197404cf5d8c0a2b818546c2227325738
1 @c This is part of the GNU tar manual.
2 @c Copyright (C) 2017--2021 Free Software Foundation, Inc.
3 @c This file is distributed under GFDL 1.3 or any later version
4 @c published by the Free Software Foundation.
6 This appendix provides several recipes for performing common tasks
7 using @GNUTAR{}.
9 @menu
10 * copy directory hierarchy::
11 * intermediate directories::
12 @end menu
14 @node copy directory hierarchy
15 @appendixsec Copying directory hierarchies
17 This is a traditional way to copy a directory hierarchy preserving
18 the dates, modes, owners and link-structure of all the files therein.
19 It was used back when the @command{cp} command lacked the @option{-a}
20 option:
22 @smallexample
23 $ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xf -)}
24 @end smallexample
26 @noindent
27 You can avoid subshells by using @option{-C} option:
29 @smallexample
30 $ @kbd{tar -C sourcedir -cf - . | tar -C targetdir -xf -}
31 @end smallexample
33 @noindent
34 The same command using long option forms:
36 @smallexample
37 @group
38 $ @kbd{(cd sourcedir; tar --create --file=- . ) \
39        | (cd targetdir; tar --extract --file=-)}
40 @end group
41 @end smallexample
43 @noindent
46 @smallexample
47 @group
48 $ @kbd{tar --directory sourcedir --create --file=- . \
49        | tar --directory targetdir --extract --file=-}
50 @end group
51 @end smallexample
53 @node intermediate directories
54 @appendixsec Restoring Intermediate Directories
56 A common concern is how to extract permissions and ownerships of
57 intermediate directories when extracting only selected members from
58 the archive.  To illustrate this, consider the following archive:
60 @example
61 @group
62 # tar tvf A.tar
63 drwxr-xr-x root/root         0 2017-11-16 14:39 foo/
64 dr-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
69 Suppose you extract only the file @file{foo/bar/file}, while being
70 @samp{root}:
72 @example
73 # @kbd{tar xvf A.tar foo/bar/file}
74 foo/bar/file
75 @end example
77 Now, let's inspect the content of the created directories:
79 @example
80 @group
81 # find foo -ls
82 427257    0 drwxr-xr-x   3 root     root    16 Nov 17 16:10 foo
83 427258    0 drwxr-xr-x   2 root     root    17 Nov 17 16:10 foo/bar
84 427259    0 -rw-r--r--   1 gray     user    10 Nov  6 14:40 foo/bar/file
85 @end group
86 @end example
88 The requested file is restored, including its ownership and
89 permissions. The intermediate directories, however, are created with
90 the default permissions, current timestamp and owned by the current
91 user. This is because by the time @command{tar} has reached the requested file,
92 it had already skipped the entries for its parent directories, so it
93 has no iformation about their ownership and modes.
95 To restore meta information about the intermediate directories,
96 you'll need to specify them explicitly in the command line and use the
97 @option{--no-recursive} option (@pxref{recurse}) to avoid extracting
98 their content.
100 To automate this process, @cite{Neal P. Murphy} proposed the following
101 shell script@footnote{The original version of the script can be
102 seen at @uref{http://lists.gnu.org/archive/html/bug-tar/2016-11/msg00024.html}}:
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
120 The script takes two arguments: the name of the archive file, and the
121 name of the file list file.
123 To complete our example, the file list will contain single line:
125 @example
126 foo/bar/file
127 @end example
129 Supposing its name is @file{file.list} and the script is named
130 @file{restore.sh}, you can invoke it as follows: 
132 @example
133 # @kbd{sh restore.sh A.tar file.list}
134 @end example