7

I would like to append both the last command and the output of the last command to a text file for the purpose of a tutorial.

For example: After I do an ls in my home directory I see this on the screen

bguiz@sheen:~$ ls
Desktop     Music    Documents

I want to then be able to enter a single command which will append the following to a textfile named cmd.txt

$ ls
Desktop     Music    Documents

The idea is that each time I enter a command, I can log both the command itself and its output to the same file, and after several commands, it will demonstrate a particular series of commands. I know this can be done manually - but why do that if there's an easy alternative, right?

This is what I've cooked up so far:

echo -n "\$ " >> cmd.txt; echo !-1:p >> cmd.txt; !-1 >> cmd.txt

It works, but is rather clunky, and has several gotchas such as not being able to preserve the exact screen formatting.

Is the a more elegant solution?


Thank you for the answers so far, but I have a requiement that it needs to work with pipe, e.g.:

ls -lart | grep ^d

Needs to get this appended in the file:

$ ls -lart | grep ^d
drwx------ 14 bguiz staff   4096 2010-03-03 15:52 .cache
drwx------  5 bguiz staff   4096 2010-03-03 09:38 .ssh

4 Answers 4

3

[script.ksh] run with "script.ksh ls"

#!/bin/ksh

OUTPUT="cmd.txt"

if [[ $# -eq 0 ]];then
  print "no command to run"
  exit
fi

# dump command being run to file
echo $@ >> $OUTPUT

# run command and output stdout to the screen and file
$@ | tee -a $OUTPUT
2
  • @Duane, thanks for the answer. I tried it, replacing $1 with $@ and that worked up until included pipes. See the edit to my main question to see what I mean.
    – bguiz
    Mar 3, 2010 at 5:39
  • I looked at this for a bit but a bit stumped... the problem is that the | is significant to the shell and never gets passed to the script. With modifications to the script you could get away with escaping the pipe (\|) but I assume that's a no-go.
    – Duane
    Mar 5, 2010 at 4:16
10

Rather simpler than the cleverness you've been trying:

$ script cmd.txt

do what you want to document here

then hit Control-d.

You can edit the file at a later date to add annotations if you wish, and you can use

$ script -a cmd.txt

to append more text to an existing file.

The available options seem to vary considerably between implementation.

  • The Mac OS X (i.e. BSD) script supports -k which logs keyboard input to the command
  • The GNU version (found on linux systems) supports -c which allows you to specify the command on the original command line, allowing you to skip the "type your demonstration here then hit control-d" bit
  • The BSD version can also specify the command on the command line but does not accept a flag for that instead it must follow the output filename (which is required in this case).

Finally the GNU version warns the vi is not well represented in type scripts (and I imagine that this warning applies equally well to all other commands that make use of curses).

3
  • @dmckee, that's great, however I want more granular control, a command entered following each command that I want to record (not all). And I also need to be able to echo "Something" >> cmd.txt" In between commands as well, for annotations.
    – bguiz
    Feb 25, 2010 at 5:13
  • script -a -c "some command" followed by some command to cleanup all of the Script started... and Script done... lines looks like it could work for me.
    – bguiz
    Feb 25, 2010 at 5:42
  • @bguiz You can do a clean-up script so that: first you make a new command that echos a marker. Then later when you want an command to be recorded you run that command. When doing clean-up you can use that marker to determine which commands you want to save. As for annotating you can do similarly a new command. It can just echo a marker with your comment.
    – Egon
    Feb 25, 2010 at 7:01
5

Write a script script.sh like the following were you insert annotation in the form of comments:

#!/bin/sh -v

# Annotating the behaviour of the ls command
ls -l

# Other comments on the next command
cmd

Note the -v switch in the first line:

-v verbose       The shell writes its input to standard error as it is read.

Then execute the script redirecting both stdout and stderr to the file cmd.txt using:

$ ./script.sh > cmd.txt 2>&1

The file cmd.txt will contain the annotations, the commands and their relative output like:

# Annotating the behaviour of the ls command
ls -l
total 1824
drwxr-xr-x 11 mrucci mrucci    4096 2010-02-14 18:16 apps
drwxr-xr-x  2 mrucci mrucci    4096 2010-02-20 12:54 bin
-rw-------  1 mrucci mrucci  117469 2010-02-25 11:02 todo.txt

# Other comments on the next command
cmd
./testscript.sh: 7: cmd: not foun

PS: remember to give execution permission to the script with:

$ chmod +x script.sh
1

In the circumstances, I generally use one of two techniques:

sh -x script

Or simply run the commands and then use copy'n'paste to save the material to a file.

The 'sh -x' output doesn't include the normal PS1 prompt - it uses the PS3 which defaults to '+ ', IIRC. And it slightly modifies the output - the details vary a bit depending on the shell you are using (so 'bash' does more messing than 'ksh' or Bourne shell do). I seldom need more material than copy'n'paste can manage, so it is my predominant modus operandi for StackOverflow and SuperUser, etc.

4
  • Neither my Mac OS 10.5 nor my Debian Lenny boxes like -x. ::sigh:: The man pages make no references to any standards for script. Last vestige of the Unix wars, I guess. Feb 25, 2010 at 6:29
  • I never had any problems with 'sh -x' on MacOS X 10.5 (or 10.4, ..., or currently on 10.6.2). Which shell are you using? 'sh -x' is common across the majority of shells - I must admit, I was not aware of any that did not support it. Feb 26, 2010 at 4:18
  • @dmckee: When you write 'sh -x', the shell does not do a path-based search for the script - you have to specify the path completely. Feb 26, 2010 at 4:20
  • Sorry. I total misunderstood. That's what I get for checking SOFU just before bed. Feb 26, 2010 at 4:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .