3 #=======================================================================
5 # File ID: 5818b856-0ba9-11de-b2c1-000475e441b9
7 # Move a whole subdirectory tree into a single .tar.gz file.
9 # Author: Øyvind A. Holm <sunny@sunbase.org>
10 # License: GNU General Public License version 2 or later.
11 #=======================================================================
62 " -n "$progname" -- "$@
")"
63 test "$?" = "0" ||
exit 1
82 opt_suffix
="$STD_SUFFIX"
91 -G|
--no-git-check) opt_no_git_check
=1; shift ;;
92 -d|
--dirs-only) opt_dirs_only
=1; shift ;;
93 -f|
--force) opt_force
=1; shift ;;
94 -h|
--help) opt_help
=1; shift ;;
95 -i|
--incremental) opt_incremental
=1; shift ;;
96 -L|
--dereference) opt_dereference
=1; shift ;;
97 -m|
--random-mac) opt_random_mac
=1; shift ;;
98 --no-uuid) opt_no_uuid
=1; shift ;;
99 --numeric-owner) opt_numeric_owner
=1; shift ;;
100 -o|
--output-dir) opt_output_dir
="$2"; shift 2 ;;
101 -P|
--prefix) opt_prefix
="$2"; shift 2 ;;
102 -q|
--quiet) opt_quiet
=$
(($opt_quiet + 1)); shift ;;
103 -r|
--remove-files) opt_remove_files
=1; shift ;;
104 -S|
--suffix) opt_suffix
="$2"; shift 2 ;;
105 -s|
--split) opt_split
="$2"; shift 2 ;;
106 -O|
--stdout) opt_stdout
=1; shift ;;
107 -v|
--verbose) opt_verbose
=$
(($opt_verbose + 1)); shift ;;
108 --version) echo $progname $VERSION; exit 0 ;;
109 -A|
--no-actime) opt_no_actime
=1; shift ;;
110 -X|
--no-xattrs) opt_no_xattrs
=1; shift ;;
111 -x|
--xz) opt_xz
=1; shift ;;
112 -z|
--gzip) opt_gzip
=1; shift ;;
114 *) echo $progname: Internal error
>&2; exit 1 ;;
117 opt_verbose
=$
(($opt_verbose - $opt_quiet))
119 if test "$opt_help" = "1"; then
120 test $opt_verbose -gt 0 && { echo; echo $progname $VERSION; }
123 Move a whole subdirectory tree into a single $STD_SUFFIX.tar.gz file.
125 Usage: $progname [options] DIRECTORY [DIRECTORIES [...]]
130 Alias for "--split 1G". No file systems should have problems with
131 this size, and it makes it easy to calculate the size of the .tar
134 Ignore non-directory arguments.
136 Don't abort if the .tar file exists, delete it before proceeding.
138 To protect against potential data loss, it first loops through all
139 arguments to check that none of them are stored in Git. If any files
140 are stored under any of the directories, it aborts. Useful with for
141 example git-annex, where only a symlink would be stored in the
142 archive file. This option disables the check.
146 Create a .snar file with information for creating incremental
147 backups. Uses the -g/--listed-incremental option in GNU tar.
149 Don't pack symlinks, include the actual files they point to.
151 Use random MAC address in UUID file label.
153 Don't create UUID label in the .tar file.
155 Use numbers for user/group names.
157 Send the .tar output to stdout instead of creating files on disk.
158 All nonsensical options are ignored, for example --split. Does not
159 work with compression.
160 -o DIR, --output-dir DIR
161 Store the tar files in DIR instead of the current directory.
162 -P PREFIX, --prefix PREFIX
163 Use PREFIX at the beginning of the tar filenames. Doesn't change the
164 name of the extracted files. Adds a terminating '.' if it doesn't
167 Be more quiet. Can be repeated to increase silence.
169 Remove files in DIRECTORY immediately after they've been added to
170 the archive. Can be used when there's not enough disk space for the
172 -S SUFFIX, --suffix SUFFIX
173 Add a custom suffix after the directory name and before the .tar
174 extension in the output filename. No changes are made to the
175 resulting tar file, only the file name is different. An intial '.'
176 is added if it's missing.
177 Default value: "$STD_SUFFIX".
178 -s SIZE, --split SIZE
179 Split the .tar file into files with SIZE bytes each. Allowed values
180 are those understood by the -b/--bytes option in split(1). These
181 files are not compressed by default, to make it easier to extract
182 data from the files without starting from the beginning.
184 Increase level of verbosity. Can be repeated.
186 Print version information.
188 Don't store atime or ctime in the tar file. Use with --no-uuid to
189 generate identical tar files.
191 Don't use --xattrs with tar(1), create standard tar archive without
192 extended attributes and nanoseconds.
194 Compress the archives with xz(1) after the files are added.
196 Compress the archives with gzip(1) after the files are added.
202 if test "$opt_xz" = "1" -a "$opt_gzip" = "1"; then
203 echo $progname: Cannot mix the
--gzip and
--xz options
>&2
207 if test "$opt_1" = "1" -a -n "$opt_split"; then
208 echo $progname: Cannot mix the
-1 and
--split options
>&2
212 if test "$opt_stdout" = "1" -a -n "$(echo $opt_gzip$opt_xz | grep 1)"; then
213 echo $progname: Cannot use compression with
-O/--stdout >&2
217 test "$opt_1" = "1" && opt_split
=1G
219 if test "$opt_dereference" = "1"; then
220 dereference_str
="--dereference"
225 if test "$opt_no_actime" = "1"; then
226 actime_str
="--pax-option=delete=atime,delete=ctime"
231 if test "$opt_random_mac" = "1"; then
232 random_mac_str
="--random-mac"
237 if test "$opt_remove_files" = "1"; then
238 rm_files_str
="--remove-files"
243 if test "$opt_no_xattrs" = "1"; then
246 xattrs_str
="--xattrs"
249 if test "$opt_numeric_owner" = "1"; then
250 numeric_str
="--numeric-owner"
256 if test -d "$f" -o "$opt_dirs_only" != "1"; then
257 if test "$opt_no_git_check" != "1"; then
258 git ls-files
"$f" |
grep -q .
>&2 && {
259 echo -n "$progname: $f: " >&2
260 if test -d "$f"; then
261 echo Files are stored
in Git below this directory
>&2
263 echo File is stored
in Git
>&2
265 echo $progname: Use
-G/--no-git-check to add it anyway
>&2
270 echo $progname: $f: Not a directory
>&2
275 if test -n "$prefix"; then
276 echo "$prefix" |
grep -q '\.$' || prefix
="$prefix."
280 if test -n "$suffix"; then
281 echo "$suffix" |
grep -q '^\.' || suffix
=".$suffix"
284 if test -n "$opt_output_dir"; then
285 if test ! -d "$opt_output_dir/."; then
286 echo "$progname: $opt_output_dir: Directory not found" >&2
289 output_dir
="$opt_output_dir/"
295 dir
="$(echo -n "$f" | sed 's/\/*$//')"
296 if [ -z "$dir" ]; then
297 echo "$progname: $f: Argument is empty after stripping slash" >&2
300 tarfile
="$output_dir$prefix$dir$suffix.tar"
302 if test $opt_verbose -ge 2; then
303 echo $progname: dir
= $dir >&2
306 if [ -d "$dir" -o "$opt_dirs_only" != "1" ]; then
308 echo $progname: Packing
$dir...
>&2
310 if test "$opt_stdout" != "1"; then
311 if ls "$tarfile"* 2>/dev
/null |
grep -q .
; then
312 if test "$opt_force" = "1"; then
315 echo "$progname: $tarfile* already exist" >&2
321 echo "$dir" |
grep -q / && {
322 echo "$progname: $dir: Slashes not allowed in the file name" >&2
326 if test "$opt_no_uuid" = "1"; then
330 suuid
-t mktar
--raw -w eo
$random_mac_str \
331 -c "<c_mktar> <filename>$tarfile</filename> <host>$(
333 )</host> <directory>$(/bin/pwd)</directory> </c_mktar>"
335 echo $progname: suuid error
>&2
338 label_str
="--label=$uuid"
340 if test "$opt_incremental" = "1"; then
341 incremental_str
="--listed-incremental $prefix$dir$suffix.snar"
345 tar_args
="$incremental_str $rm_files_str"
346 tar_args
="$tar_args --force-local $actime_str --sort=name --sparse"
347 tar_args
="$tar_args $dereference_str $numeric_str $xattrs_str"
348 tar_args
="$tar_args $label_str"
349 if test "$opt_stdout" = "1"; then
350 echo $progname: Sending to stdout
>&2
351 echo $progname: tar c
$tar_args $dir >&2
352 tar c
$tar_args "$dir" ||
exit 1
355 if test -n "$opt_split"; then
356 echo $progname: tar c
$tar_args $dir \
357 \|
split -b $opt_split --verbose - $tarfile.split_
>&2
358 tar c
$tar_args "$dir" \
359 |
split -b $opt_split --verbose - "$tarfile.split_" ||
exit 1
360 if test ! -e "$tarfile.split_ab"; then
361 mv -vi "$tarfile.split_aa" "$tarfile" ||
exit 1
363 test "$opt_xz" = "1" && xz
-v "$tarfile"*
364 test "$opt_gzip" = "1" && gzip -vn --rsyncable "$tarfile"*
366 echo $progname: tar cf
$tarfile $tar_args $dir >&2
367 tar cf
"$tarfile" $tar_args "$dir" ||
exit 1
368 if test "$opt_stdout" != "1"; then
369 du
--si "$tarfile" >&2
370 test "$opt_xz" = "1" && xz
-v "$tarfile"
371 test "$opt_gzip" = "1" && gzip -vn --rsyncable "$tarfile"