[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