bug-tar
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-tar] [PATCH] clarification on variable expansion and best practice


From: Stephane Chazelas
Subject: [Bug-tar] [PATCH] clarification on variable expansion and best practice fixes in examples.
Date: Thu, 14 Apr 2016 08:53:21 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

2016-04-13 23:08:56 +0300, Sergey Poznyakoff:
> Stephane Chazelas <address@hidden> ha escrit:
> 
> > It would seem "tar" doesn't  invoke a shell to process that
> 
> What tar version are you using then?
[...]

That was with 1.28, but I can reproduce with the latest git
master from savannah.

$ tar cf - /etc/issue | strace -fe execve src/tar xf - --to-command='echo a > b'
tar: Removing leading `/' from member names
execve("src/tar", ["src/tar", "xf", "-", "--to-command=echo a > b"], [/* 27 
vars */]) = 0
Process 8978 attached
[pid  8978] execve("/usr/bin/echo", ["echo", "a", ">", "b"], [/* 44 vars */]) = 
-1 ENOENT (No such file or directory)
[pid  8978] execve("/bin/echo", ["echo", "a", ">", "b"], [/* 44 vars */]) = 0
a > b
[pid  8978] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8978, si_status=0, 
si_utime=0, si_stime=0} ---
+++ exited with 0 +++


IMO, it would make more sense for tar to  invoke a shell here
instead of doing a shell-like parsing that is going to confuse
people (it even confused you! ;-)).

Please find a doc patch below which tries to clarify and improve
examples so they follow best shell coding practice.

---
Add a note that word splitting is performed on variable
expansions within executed commands (as with --to-command). Note
that a shell is not invoked.

Fixed missing quotes around variable expansions in some shell snipets
and various other shell coding best practice fixes.
---
 doc/tar.texi | 49 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/doc/tar.texi b/doc/tar.texi
index af4d9d8..8f80799 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_FILENAME'}
+     --checkpoint-action='exec=/sbin/cpoint "$TAR_FILENAME"'}
 @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 by @command{tar}.
 
 Any number of actions can be defined, by supplying several
 @option{--checkpoint-action} options in the command line.  For
@@ -4737,7 +4738,7 @@ command line of the external command.  For example:
 
 @smallexample
 $ @kbd{tar -x -f archive.tar \
-    --checkpoint=exec='printf "%04d in %32s\r" $TAR_CHECKPOINT $TAR_ARCHIVE'}
+   --checkpoint=exec='printf "%04d in %32s\r" "$TAR_CHECKPOINT" 
"$TAR_ARCHIVE"'}
 @end smallexample
 
 @noindent
@@ -4747,6 +4748,23 @@ 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 by @command{tar}.
+
+Variable expansions should be quoted unless they need to be treated as
+(space or tab separated) lists.
+
+No filename generation, tilde expansion, redirection is performed by
address@hidden If those shell features are needed, one needs to invoke a
+shell explicitly. A convenient way to do it is by passing the shell code
+as an environment variable:
+
address@hidden
+$ @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"'}
address@hidden smallexample
+
 @node operations
 @chapter @GNUTAR{} Operations
 
@@ -6282,12 +6300,13 @@ 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 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 +6518,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 +6533,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 +7265,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 +7562,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 +12270,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 : '\(.*\)-.*'`
address@hidden@}
 case $TAR_SUBCOMMAND in
 -c)       ;;
--d|-x|-t) test -r address@hidden:address@hidden || exit 1
+-d|-x|-t) test -r "$name-$TAR_VOLUME" || exit 1
           ;;
 *)        exit 1
 esac
 
-echo address@hidden:address@hidden >&$TAR_FD
+printf '%s\n' "$name-$TAR_VOLUME" >&$TAR_FD
 @end group
 @end smallexample
 
-- 
Stephane



reply via email to

[Prev in Thread] Current Thread [Next in Thread]