2016-04-14 11:55:29 +0300, Sergey Poznyakoff: > Stephane Chazelas <[email protected]> ha escrit: > > > That was with 1.28, but I can reproduce with the latest git > > master from savannah. > > Indeed. That behavior was broken in v. 1.27. I've pushed a patch to > fix it. > > Thanks for bringing my attention to it. [...]
Thanks. Updated documentation patch below. Note that you forgot to quote the variables in your latest change to the doc. You may want to read https://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells if you're not familiar with the need to quote variables in shells. diff --git a/doc/tar.texi b/doc/tar.texi index a8969e0..4d7db4f 100644 --- a/doc/tar.texi +++ b/doc/tar.texi @@ -4482,12 +4482,13 @@ command, provided that they are properly escaped, for example: @smallexample @kbd{tar -c -f arc.tar \ - --checkpoint-action='exec=/sbin/cpoint $TAR_CHECKPOINT'} + --checkpoint-action='exec=/sbin/cpoint "$TAR_CHECKPOINT"'} @end smallexample @noindent Notice single quotes to prevent variable names from being expanded by -the shell when invoking @command{tar}. +the shell when invoking @command{tar}. And the double quotes to prevent +word splitting or filename generation by the shell invoked by @command{tar}. Any number of actions can be defined, by supplying several @option{--checkpoint-action} options in the command line. For @@ -4721,12 +4722,8 @@ feature is the @option{-I} option, which allows you to supply the program to use for compressing or decompressing the archive (@pxref{use-compress-program}). -Whenever such operation is requested, @command{tar} first splits the -supplied command into words much like the shell does. It then treats -the first word as the name of the program or the shell script to execute -and the rest of words as its command line arguments. The program, -unless given as an absolute file name, is searched in the shell's -@env{PATH}. +@command{tar} invokes a shell (@command{/bin/sh}) to parse the supplied +command line. Any additional information is normally supplied to external commands in environment variables, specific to each particular operation. For @@ -4737,7 +4734,7 @@ command line of the external command. For example: @smallexample $ @kbd{tar -x -f archive.tar \ - --checkpoint-action=exec='printf "%04d in %32s\r" $TAR_CHECKPOINT $TAR_ARCHIVE'} + --checkpoint-action=exec='printf "%04d in %32s\r" "$TAR_CHECKPOINT" "$TAR_ARCHIVE"'} @end smallexample @noindent @@ -4747,6 +4744,25 @@ archive, using the same output line on the screen. Notice the use of single quotes to prevent variable names from being expanded by the shell when invoking @command{tar}. +And the double quotes to prevent word splitting and filename generation +by the shell invoked by @command{tar}. + +Note that while a shell is now invoked to parse that command line, but +note that versions 1.27 and 1.28 of @command{tar} used not to but +instead used a simplified command line parser that did not support shell +redirection or expansions other than simple variable expansion. + +If writing a script to be compatible with those earlier versions, you +can use this approach to make sure a shell is always invoked to parse +the command line regardless of the version of @command{tar}. + +@smallexample +$ @kbd{SH_CODE=' + printf "%04d in %32s\r" "$TAR_CHECKPOINT" "$TAR_ARCHIVE" | + tee -a ~/some-file + ' tar -x -f archive.tar --checkpoint=exec='sh -c "$SH_CODE"'} +@end smallexample + @node operations @chapter @GNUTAR{} Operations @@ -6282,12 +6298,14 @@ could do: @smallexample $ @kbd{tar -x -f archive.tar \ - --to-command='proc $TAR_FILENAME $TAR_SIZE'} + --to-command='proc "$TAR_FILENAME" "$TAR_SIZE"'} @end smallexample @noindent Notice single quotes to prevent variable names from being expanded by -the shell when invoking @command{tar}. +the shell when invoking @command{tar}. And the double quotes to prevent +word splitting and filename generation by the shell invoked by +@command{tar}. If @var{command} exits with a non-0 status, @command{tar} will print an error message similar to the following: @@ -6499,7 +6517,7 @@ link-structure of all the files therein. In this case, the transfer medium is a @dfn{pipe}: @smallexample -$ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xf -)} +$ @kbd{(cd sourcedir && tar -cf - .) | (cd targetdir && tar -xf -)} @end smallexample @noindent @@ -6514,8 +6532,8 @@ The command also works using long option forms: @smallexample @group -$ @kbd{(cd sourcedir; tar --create --file=- . ) \ - | (cd targetdir; tar --extract --file=-)} +$ @kbd{(cd sourcedir && tar --create --file=- . ) \ + | (cd targetdir && tar --extract --file=-)} @end group @end smallexample @@ -7246,7 +7264,7 @@ RSH_COMMAND=/usr/bin/ssh # Override MT_STATUS function: my_status() @{ - mts -t $TAPE_FILE + mts -t "$TAPE_FILE" @} MT_STATUS=my_status @@ -7543,7 +7561,7 @@ The following example is a convenient way of copying directory hierarchy from @file{sourcedir} to @file{targetdir}. @smallexample -$ @kbd{(cd sourcedir; tar -cf - .) | (cd targetdir; tar -xpf -)} +$ @kbd{(cd sourcedir && tar -cf - .) | (cd targetdir && tar -xpf -)} @end smallexample The @option{-C} option allows to avoid using subshells: @@ -12251,21 +12269,21 @@ archive being created (as given by @option{--file} option) and @smallexample @group -#! /bin/bash +#! /bin/bash - # For this script it's advisable to use a shell, such as Bash, # that supports a TAR_FD value greater than 9. -echo Preparing volume $TAR_VOLUME of $TAR_ARCHIVE. +echo "Preparing volume $TAR_VOLUME of $TAR_ARCHIVE." -name=`expr $TAR_ARCHIVE : '\(.*\)-.*'` +name=$@{TAR_ARCHIVE%-*@} case $TAR_SUBCOMMAND in -c) ;; --d|-x|-t) test -r $@{name:-$TAR_ARCHIVE@}-$TAR_VOLUME || exit 1 +-d|-x|-t) test -r "$name-$TAR_VOLUME" || exit 1 ;; *) exit 1 esac -echo $@{name:-$TAR_ARCHIVE@}-$TAR_VOLUME >&$TAR_FD +printf '%s\n' "$name-$TAR_VOLUME" >&$TAR_FD @end group @end smallexample -- Stephane
