- How do I redirect output to a variable in shell? [duplicate]
- 8 Answers 8
- The answer to the question is to use the read command.
- Here’s how you do it
- Here is what it is doing and why it is important:
- Перенаправление stdout и stderr в переменные
- BASH command output to the variable
- Command Substitution Syntax:
- Single command output to a variable
- Example#1:
- Example#2:
- Example#3:
- Example#4:
- Using command substitution in loop
- Example#5:
- Using nested commands
- Example#6:
- Using Command path
- Example#7:
- Using Command Line argument
- Example#8:
- Conclusion:
- About the author
- Fahmida Yesmin
How do I redirect output to a variable in shell? [duplicate]
I want to get stream generated by genhash in a variable. How do I redirect it into a variable $hash to compare inside a conditional?
if [ $hash -ne 0 ] then echo KO exit 0 else echo -n OK exit 0 fi
This question is the older than the linked answer. Therefore the linked answer is the duplicate, and should be marked as «asked before», not this one.
Bash and Shell are different things, hence it’s no duplicate. Shell doesn’t support all of bash’s features.
8 Answers 8
hash=$(genhash --use-ssl -s $IP -p 443 --url $URL | grep MD5 | grep -c $MD5)
This captures the output of a command, but it does not use a redirect. If you actually need to use a redirect because of a more complex need, See my answer. Google brought you here, right? Why go somewhere else to find the answer you searched for?
@Kayvar when you use $( . ) it uses new subshell, so the result of command can be not the same as in the primary shell
It would be helpful to others if you made it clear whether this only captures STDOUT or if it also captures STDERR. It would also be very helpful if you could show how to print the exit code of the command inside $(. )
But, because pipes create forks, you have to use $foo before the pipe ends, so.
echo "abc" | ( read foo; date +"I received $foo on %D"; )
Sure, all these other answers show ways to not do what the OP asked, but that really screws up the rest of us who searched for the OP’s question.
The answer to the question is to use the read command.
Here’s how you do it
# I would usually do this on one line, but for readability. series | of | commands \ | \ ( read string; mystic_command --opt "$string" /path/to/file ) \ | \ handle_mystified_file
Here is what it is doing and why it is important:
- Let’s pretend that the series | of | commands is a very complicated series of piped commands.
- mystic_command can accept the content of a file as stdin in lieu of a file path, but not the —opt arg therefore it must come in as a variable. The command outputs the modified content and would commonly be redirected into a file or piped to another command. (E.g. sed , awk , perl , etc.)
- read takes stdin and places it into the variable $string
- Putting the read and the mystic_command into a «sub shell» via parenthesis is not necessary but makes it flow like a continuous pipe as if the 2 commands where in a separate script file.
There is always an alternative, and in this case the alternative is ugly and unreadable compared to my example above.
# my example above as a oneliner series | of | commands | (read string; mystic_command --opt "$string" /path/to/file) | handle_mystified_file # ugly and unreadable alternative mystic_command --opt "$(series | of | commands)" /path/to/file | handle_mystified_file
My way is entirely chronological and logical. The alternative starts with the 4th command and shoves commands 1, 2, and 3 into command substitution.
I have a real world example of this in this script but I didn’t use it as the example above because it has some other crazy/confusing/distracting bash magic going on also.
Перенаправление stdout и stderr в переменные
1. Как мне перенаправить вывод команды в отдельные переменные? Гуглятся такие варианты, но как это работает не пойму, может можно селать как-то проще?
2. При выводе в переменную с последующим ее echo у меня результат будет только как отработает команда. Можно ли как-то организовать аналог tail -f для переменной?
Все это желательно сделать без промежуточных файлов, но если не получится придется наверно делать с fifo.
Это эталонный топик для лора:
автор как обычно не описывает задачу, а описывает свои фантазии на тему как эта задача должна решаться.
Дальше начинается слёт телепатов и прочих доброжелателей
#!/bin/bash simple_function() < OUT=$(ping -c 4 localhost) ERR=. echo $OUT echo $ERR > simple_function
Кавычки (обратные) не перепутай
1. Как мне перенаправить вывод команды в отдельные переменные?
ping -q -c 5 google.com > /dev/null 2>&1 STATCODE="$?" echo "$STATCODE" 0 #либо ping -q -c 5 wewqreuadfhadfdgd.com > /dev/null 2>&1 STATCODE="$?" echo "$STATCODE" 2
Success: code 0
No reply: code 1
Other errors: code 2
пиши на тикле, там vwait есть.
Так stdout мне тоже нужен
Ну тогда man mktemp, но я думаю ты и сам до этого догадаешься.
По второму вопросу — coprocess, но это чёрная магия и лучше её не использовать:
#!/bin/bash coproc ping -c 20 -n 127.0.0.1 for i in 1 2 3 4 5 6 7 8 9 A ; do read var " echo i is $i ";" var is $var sleep 1 done
Примеры по вашей ссылки по первому вопросу основаны на том, что можно получить stdout и stdin через Process Substitution, но это будут подпроцессы, чтобы передать значения переменных в основной процесс их выводят через ″typeset -p″, а потом превращают в переменные через ″eval″. Лично я бы предпочёл использование временных файлов ( ″mktemp″), чем через год понимать что это за код, завёрнутый в ″eval″.
mky ★★★★★ ( 04.07.14 00:08:18 MSK )
Последнее исправление: mky 04.07.14 00:08:33 MSK (всего исправлений: 1)
capture() < local cmd="$1" local stdout="$2" local stderr="$3" local f_stdout=$(mktemp) local f_stderr=$(mktemp) $cmd >$f_stderr 2>$f_stdout local _ifs=$IFS eval "IFS= $stdout=\$(cat '$f_stdout')" eval "IFS= $stderr=\$(cat '$f_stderr')" IFS=$_ifs rm -f "$f_stderr" "$f_stdout" > capture "ping -c 3 whatever.org" PING_STDOUT PING_STDERR echo STDOUT: $PING_STDOUT echo STDERR: $PING_STDERR
KennyMinigun ★★★★★ ( 04.07.14 01:12:04 MSK )
Последнее исправление: KennyMinigun 04.07.14 01:21:48 MSK (всего исправлений: 1)
- $cmd >$f_stderr 2>$f_stdout + $cmd >$f_stdout 2>$f_stderr
BASH command output to the variable
Different types of bash commands need to be run from the terminal based on the user’s requirements. When the user runs any command from the terminal then it shows the output if no error exists otherwise it shows the error message. Sometimes, the output of the command needs to be stored in a variable for future use. Shell command substitution feature of bash can be used for this purpose. How you can store different types of shell commands into the variable using this feature is shown in this tutorial.
Command Substitution Syntax:
variable =$ ( command )
variable =$ ( command [ option… ] argument1 arguments2 … )
variable =$ ( / path / to / command )
variable = ` command `
variable = ` command [ option… ] argument1 arguments2 … `
variable = `/ path / to / command `
***Note: Don’t use any space before and after the equal sign when using the above commands.
Single command output to a variable
Bash commands can be used without any option and argument for those commands where these parts are optional. The following two examples show the uses of simple command substitution.
Example#1:
bash `date` command is used to show the current date and time. The following script will store the output of `date` command into $current_date variable by using command substitution.
Example#2:
`pwd` command shows the path of the current working directory. The following script stores the output of `pwd` command into the variable, $current_dir and the value of this variable is printed by using `echo` command.
Command with option and argument
The option and argument are mandatory for some bash commands. The following examples show how you can store the output of the command with option and argument into a variable.
Example#3:
Bash `wc` command is used to count the total number of lines, words, and characters of any file. This command uses -c, -w and -l as option and filename as the argument to generate the output. Create a text file named fruits.txt with the following data to test the next script.
fruits.txt
Run the following commands to count and store the total number of words in the fruits.txt file into a variable, $count_words and print the value by using `echo` command.
Example#4:
`cut` is another bash command that uses option and argument to generate the output. Create a text file named weekday.txt with seven-weekday names to run the next script.
Create a bash file named cmdsub1.sh with the following script. In this script, while loop is used to read the content of weekday.txt file line by line and read the first three characters of each line by using `cut` command. After cutting, the string value is stored in the variable $day. Next, If the statement is used to check the value of $day is ‘Sun’ or not. The output will print ‘Sunday is the holiday‘ when if the condition is true otherwise it will print the value of $day.
#!/bin/bash
filename = ‘weekday.txt’
while read line; do
day = ` echo $line | cut -c 1 — 3 `
if [ $day == «Sun» ]
then
echo «Sunday is the holiday»
else
echo $day
fi
done < $filename
Using command substitution in loop
You can store the output of command substitution into any loop variable which is shown in the next example.
Example#5:
Create a file named cmdsub2.sh with the following code. Here, `ls -d */` command is used to retrieve all directory list from the current directory. For loop is used here to read each directory from the output and store it in the variable $dirname which is printed later.
Using nested commands
How you can use multiple commands using pipe(|) is shown in the previous example. But you can use nested commands in command substitution where the output of the first command depends on the output of the second command and it works opposite of the pipe(|) command.
Nested command syntax:
Example#6:
Two commands, `echo` and `who` are used in this example as the nested command. Here, `who` command will execute first that print the user’s information of the currently logged in user. The output of the `who` command will execute by `echo` command and the output of `echo` will store into the variable $var. Here, the output of `echo` command depends on the output of `who` command.
Using Command path
If you know the path of the command then you can run the command by specifying the command path when using command substitution. The following example shows the use of command path.
Example#7:
`whoami` command shows the username of the currently logged in user. By default, this command is stored in /usr/bin/ folder. Run the following script to run `whoami` command using path and store in the variable, $output, and print the value of $output.
Using Command Line argument
You can use the command line argument with the command as the argument in the command substitution.
Example#8:
Create a bash file named cmdsub3.sh with the following script. `basename` command is used here to retrieve the filename from the 2 nd command line argument and stored in the variable, $filename. We know the 1 st command line argument is the name of the executing script which is denoted by $0.
Run the script with the following argument value.
Here, the basename of the path, Desktop/temp/hello.txt is ‘hello.txt’. So, the value of the $filename will be hello.txt.
Conclusion:
Various uses of command substitutions are shown in this tutorial. If you need to work with multiple commands or depended commands and store the result temporary to do some other tasks later then you can use this feature in your script to get the output.
About the author
Fahmida Yesmin
I am a trainer of web programming courses. I like to write article or tutorial on various IT topics. I have a YouTube channel where many types of tutorials based on Ubuntu, Windows, Word, Excel, WordPress, Magento, Laravel etc. are published: Tutorials4u Help.