0

I was attempting to run a script in bash: cc.sh

To run the bash script:

../cc.sh ../seq/ seqf

where ../seq/ and seqf are both arguments required.

I wanted to save the command I used to run the script (the command above), together with the output/result from the script into a log file.

I managed to print the output into a log file with tee command.

../cc.sh ../seq/ seqf 2<&1 | tee -a cc.log

cat cc.log:

"here is where the output shown"

While for the command itself, the closest I got is the script command. However, it seemed to save the command I used to run in a binary file.

Is there other better way to print the command other than script? Or better, print the command used to run the script file, together with the output/result into a log file?

Expected output for the log file:

COMMAND: ../cc.sh ../seq/ seqf
"here is where the output shown"
1
  • script saves the output exactly as it is sent to your terminal. That means that fancy prompts and carriage returns show up as escape sequences. "Certain interactive commands, such as vi(1), create garbage in the typescript file. script works best with commands that do not manipulate the screen, the results are meant to emulate a hardcopy terminal." - from the man page.
    – user516667
    Aug 2, 2022 at 8:58

2 Answers 2

2

The simplest way is to modify your script to make it print its name and argument list to standard output. For example, if the file of your script contains echo $0 $@ as the first line, it will print the info you need (assuming it uses sh and is launched from bash):

#!/bin/sh
echo "$0 $@"

and then you can just redirect stdout to file, tee or whatever you want.

6
  • 1
    Since it looks like you're intending to output the command and its arguments as a single string, it would make more sense to use $*.
    – Kusalananda
    Aug 2, 2022 at 11:48
  • @terdon, would you like to show me the case in which the quoting will be necessary here?
    – Main Furr
    Aug 2, 2022 at 13:08
  • 1
    @MainFurr sure, run it as foo.sh "*" for example. It should print foo.sh * but if you leave it unquoted, it will print foo.sh and then everything in the current directory.
    – terdon
    Aug 2, 2022 at 13:10
  • @terdon seems like bash behaves differently from csh, and I didn't pay attention to interpreting when called the bash with test script as argument from csh. Ok, thanks.
    – Main Furr
    Aug 2, 2022 at 13:29
  • Thanks @MainFurr! In this specific case, $0 will print ../cc.sh, while $@ print the rest of the arguments that come after, is that true?
    – web
    Aug 2, 2022 at 23:53
2

Use an array to store the command and its arguments. Print the command (the array) to the output file, then execute the command. Pipe all output to tee to append it to the cc.log file:

mycommand=( ../cc.sh ../seq/ seqf )

{
    printf 'COMMAND: %s\n' "${mycommand[*]}"
    "${mycommand[@]}"
} | tee -a cc.log

This creates the array mycommand and sets its elements to the command and its arguments. The command is then printed, prefixed by the string COMMAND: . The expansion "${mycommand[*]}" will be a single string made up of the elements of the array delimited by the first character of $IFS (usually a space).

The expansion "${mycommand[@]}" will be a list of individual quoted strings, i.e. the command and its individually quoted arguments. Using the expansion like this would cause the command to be correctly invoked.

The output from both printf and the command is redirected together to tee, one after the other, since they are part of the same compound command ({...;}).

Or, using the list of positional parameters instead of a named array,

set -- ../cc.sh ../seq/ seqf

{
    printf 'COMMAND: %s\n' "$*"
    "$@"
} | tee -a cc.log

Note that this would work for any command, whether a shell script or a compiled binary executable.

You must log in to answer this question.

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