Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Here is a script from Mercurial issue 2743. Call it mq.sh. I'm trying to get it to do the following things, on Debian squeeze.

  1. Echo commands + standard output + standard error to a file.

  2. Prefix with working directory. Sticking in $PWD doesn't work, as it presumably just keeps using the value from when it was first
    sourced.

  3. Reset redirection back to normal standard output/error at the end. I'm not sure how to do this, but I imagine I'd have to use exec again.

  4. I'm calling this with sh mq.sh. I'd like to do everything portably (if possible), and it seems exec is bash-specific, so I'm puzzled why this is working. Also set -x xtrace is probably bash specific as well. I got it from the Bash reference manual. Doesn't calling with sh run everything through dash on Debian?

1 currently works, I think. How do I do 2 and 3? And can I have a clarification on 4?

export PS4="$PWD$ "
exec > mq.log 2>&1
export HG="hg-crew"
rm -r main clone

set -o xtrace
$HG init main
cd main
$HG init --mq
$HG qnew foo
echo a > a
$HG add
$HG qref
$HG ci --mq -Am.
cd ..
$HG qclone main clone
cd clone
$HG paths --mq
mv .hg/patches/.hg/hgrc{,.foo}
$HG paths --mq
$HG push --mq
echo b >> a
$HG qref
$HG ci --mq -m.
mv .hg/patches/.hg/hgrc.foo .hg/patches/.hg/hgrc
$HG push --mq
share|improve this question
1  
There's a command called script that might make your life easier. script — make typescript of terminal session –  Mikel May 6 '11 at 22:50
    
Resources if you're interested in shell portability: Single Unix v3, also available as susv3 on Debian; also older shell manuals. On Debian, both dash and posh are shell with few non-standard extensions. –  Gilles May 6 '11 at 23:06
    
@Gilles: Thanks for the pointers. –  Faheem Mitha May 7 '11 at 19:08

2 Answers 2

up vote 3 down vote accepted

exec for file descriptors and set -x are portable; xtrace is not, but should actually be the same thing as -x.

To save and restore file descriptors, you do indeed use exec again. You need to pick some unused descriptors, which usually means anything over 2, and redirect the originals to those, then redirect back at the end.

exec 20<&0 21>&1 22>&2
# do your redirections
# do whatever you wanted to have redirected
exec <&20 >&21 2>&22 20<&- 21>&- 22>&-

The last line first dup()s the saved file descriptors back where they came from, then closes (&-) the copies. The closes are probably unnecessary but a good idea.

Also note that, if this is being run in its own shell, the redirections go away when the shell does. You would only need to undo the redirection if you were using . (portable) or source (bash).

share|improve this answer
    
@geekosaur: Thanks. What about 2? Not sure what you mean by "xtrace is not, but should actually be the same thing as -x." So is set -o xtrace portable or not? I'll try to understand what the exec redirections are about. Do you have a good reference for this? –  Faheem Mitha May 6 '11 at 22:32
    
set -o xtrace is not portable, but its meaning in bash is the same as the portable version, set -x. Redirections you can find documented in gnu.org/software/bash/manual/bashref.html#Redirections — note section 3.6.8 in particular. (3.6.9 is, however, bash-specific.) –  geekosaur May 6 '11 at 22:58
    
set -o xtrace has been standard for a while. Bourne only had set -x IIRC. exec redirections were already in Bourne as well, but only with single-digit file descriptors on some systems. –  Gilles May 6 '11 at 23:09
    
@Gilles: If set -o xtrace and set -x are equivalent and both portable, then which should be preferred? You are referencing Bourne as a precursor to the POSIX standard? –  Faheem Mitha May 7 '11 at 0:31
    
@Faheem: The Bourne shell was /bin/sh during Unix's formative years. The POSIX standard was mainly a compromise between the then-already-elderly Bourne shell and the more featureful, but not universally available Korn shell. The Almquist (the BSD replacement for the non-free Bourne shell) had set -x from day one, but didn't acquire set -o until later. So set -x will get you portability to more older (pre-POSIX) platforms. –  Gilles May 7 '11 at 10:49

For the working directory, try PS4='+$PWD '. The single quotes mean it only gets expanded when it's about to be printed. The first character of PS4 can be printed multiple times, so you probably still want the + or at least a space at the start.

According to POSIX definition of set, set -x and set -o xtrace are both supported. The dash man page says it's OK too.

share|improve this answer
    
Thanks. The single quote does indeed work. So, single quotes protect against expansion, so in this case, I guess the '$PWD$ ' gets substituted as is wherever the set -x uses it, and then gets expanded there. Right? I'm not, however, clear on what you mean by The first character of PS4 can be printed multiple times.... Can you elaborate? –  Faheem Mitha May 7 '11 at 19:31

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.