yart
yart

Reputation: 7805

How to capture output of several commands?

I have command producing output belonging to different commands.

s=$(time dd if=<source> of=/dev/null bs=<number> count=<number> 2>&1)

$s will contain output only from dd command. How can I have another variable which will contain the output from time?

Upvotes: 4

Views: 186

Answers (3)

wich
wich

Reputation: 17157

Try the following:

s=$({ time dd ... > /dev/null;} 2>&1)

Chepners answer gave me inspiration for the arguably better:

s=$(exec 2>&1; time dd ... > /dev/null)

$() is already a subshell, so no need to create an extra subshell. Putting exec 2>&1; before the command redirects the stdout of the entire subshell, putting it after the command would make it part of the command to time and hence is applied only to the command passed to time. Omitting the exec and semicolon will try to execute the system time binary intead of the builtin, and error out if that does not exist. Omitting just the exec but keeping the semicolon will not work as that would cause only newly forked processes to be redirected and the time builtin will not be a new process.

Oh and by the way, the > /dev/null does not dump the output of time itself to /dev/null because it too is part of the command that time executes and is not applied to time itself.

Upvotes: 3

chepner
chepner

Reputation: 532133

The bash built-in time is a special built-in that writes to standard error of the current shell, so you cannot simply redirect its output. Instead, you would need to run it in a subshell whose standard error has already been redirected. This causes the "real" command to also run in a subshell, so you can't simply assign its output to variable, as that variable will go away with the subshell. Try this:

s=$( exec 2>time.txt; time echo foo )
t=$(< time.txt)

Upvotes: 1

yart
yart

Reputation: 7805

Hello I just find out the answer.

The link from Vlad in comments gave me direction.

I can use subshells.

My command could be specified

s=$((time dd if=<source> of=/dev/null bs=<number> count=<number> 2>&1 | tail -n1) 2>&1)

Then I can have $s variable containing all data and I can have array and get values.

Upvotes: 1

Related Questions