writing file using cat with here-document - bash

$ cat > out.txt <<EOF
> Hello world
> EOF
$
How do I do this in single statement?
Somethig like 'echo' in following statement
$ for i in {1..5}; do echo "Hello world" > out_$i.txt; done

You can use a here-string, which is a shortcut for short here documents in bash.
cat <<< "Hello world" > out.txt

Related

bash run script from here doc [duplicate]

This question already has answers here:
Using variables inside a bash heredoc
(3 answers)
Closed 3 years ago.
In the code below, variable X is output normally.
# cat a.sh
X=world
echo 'hello' $X
# cat a.sh | bash
hello world
But, using here doc, variable X is not displayed.
# cat <<EOF | bash
> X=world
> echo 'hello' $X
> EOF
hello
# bash -s <<EOF
> X=world
> echo 'hello' $X
> EOF
hello
What made this difference?
You can see what happens when you remove the |bash
X=oldvalue
cat <<EOF
X=world
echo "hello $X"
EOF
The $X is replaced before piping it to bash.
You can check the following
X=oldvalue
cat <<"EOF"
X=world
echo "hello $X"
EOF
This is what you want to execute:
cat <<"EOF" | bash
X=world
echo "hello $X"
EOF

How do I get a variable value that is stored in a string in a file?

I have a file with strings that include variables. I want to retrieve the string with the value of the variable being represented in the string. I have tried ${!var} without success.
A file called test.line with the string and a variable:
$ cat test.line
Hello $var3
A bash script called test.sh:
$ cat test.sh
#!/bin/bash
var1="hello"
var2="goodbye"
var3="again"
## works
str="$var1 and $var2"
echo $str
## does not work--prints $var3 instead of "again"
str="$(cat test.line)"
echo $str
Output of test.sh when run:
$ ./test.sh
hello and goodbye
Hello $var3
Desired output of test.sh when run:
$ ./test.sh
hello and goodbye
Hello again
$ cat test.sh
#!/bin/bash
var1="hello"
var2="goodbye"
var3="again"
## works
str="$var1 and $var2"
echo $str
## SOLVED -- Does work
str="$(cat test.line)"
eval echo $str # This is the line that SOLVED it
Output of test.sh when run:
$ ./test.sh
hello and goodbye
Hello again ##This is what I want (SOLVED)

Capture output of a timed out command using Ubuntu `timeout`

Related questions:
This question ended up not requiring a resolution.
This question had a resolution not involving timeout, but suggested that timeout should work for this purpose when available.
My question:
This command produces no output into foo.txt:
$ cat foo.sh
#!/bin/sh
sh -c "echo foo; sleep 5; echo bar" | awk '/foo/ {print $1}'
$ timeout 2 ./foo.sh > foo.txt
If I don't redirect into foo.txt, I see foo print out immediately as expected.
On the other hand, the following produces "foo" int the file foo.txt as expected:
$ timeout 2 sh -c "echo foo; sleep 5; echo bar" > foo.txt
$ cat foo.txt
foo
Does anyone know why this may be happening and how best to resolve it? This is a toy example, but the actual script I'm running that led to this problem produces around 100 lines of output on the command line, but also leaves foo.txt empty if it times out before terminating.
I found a solution to this. The key is to add fflush() inside the awk script, which seemed to be buffering the output:
#!/bin/sh
sh -c "echo foo; sleep 5; echo bar" | awk '/foo/ {print $1; fflush()}'
$ timeout 2 ./foo.sh > foo.txt
In my experience, this is because pipe "|" wait "echo foo; sleep 5; echo bar" run complete .So after 5s awk can get the output, but timeout terminate the command in 2s so it cannot get the text.
Edit:
Maybe this helps, you can move char (") to the end like this:
$ cat foo.sh
#!/bin/sh
sh -c "echo foo; sleep 5; echo bar | awk '/foo/ {print $1;}'"
$ timeout 2 ./foo.sh > foo.txt
$ cat foo.txt
foo

bash/zsh input process substitution gives syntax error in conjunction with while

These work fine and do what they should (print the contents of the file foo):
cat <foo
while read line; do echo $line; done <foo
cat <(cat foo)
However this gives me a syntax error in zsh:
zsh$ while read line; do echo $line; done <(cat foo)
zsh: parse error near `<(cat foo)'
and bash:
bash$ while read line; do echo $line; done <(cat foo)
bash: syntax error near unexpected token `<(cat foo)'
Does anybody know the reason and maybe a workaround?
Note: This is obviously a toy example. In the real code I need the body of the while loop to be executed in the main shell process, so I can't just use
cat foo | while read line; do echo $line; done
You need to redirect the process substitution into the while loop:
You wrote
while read line; do echo $line; done <(cat foo)
You need
while read line; do echo $line; done < <(cat foo)
# ...................................^
Treat a process substitution like a filename.
bash/zsh replaces <(cat foo) by a pipe (kind of file) having a name as /dev/fd/n where n is the file descriptor (number).
You can check the pipe name using the command echo <(cat foo).
As you may know, bash/zsh also runs the command cat foo in another process. The output of this second process is written to that named pipe.
without process substitution:
while ... do ... done inputfile #error
while ... do ... done < inputfile #correct
same rules using process substitution:
while ... do ... done <(cat foo) #error
while ... do ... done < <(cat foo) #correct
Alternative:
cat foo >3 & while read line; do echo $line; done <3;
I can suggest only workaround like this:
theproc() { for((i=0;i<5;++i)) do echo $i; }
while read line ; do echo $line ; done <<<"$(theproc)"

Opening a file in write mode

I have a file called a.txt. with values like
1
2
3
...
I want to overwrite this file but
echo "$var" >> a.txt
echo "$var1" >> a.txt
echo "$var2" >> a.txt
...
just appends. Using > is not useful as well. How can i overwrite with using >> operator in shell script?
You may want to use > for the first redirection and >> for subsequent redirections:
echo "$var" > a.txt
echo "$var1" >> a.txt
echo "$var2" >> a.txt
> truncates the file if it exists, and would do what you originally asked.
>> appends to the file if it exists.
If you want to overwrite the content of a file (not truncate it), use 1<>
e.g.:
[23:58:27 0 ~/tmp] $ echo foobar >a
[23:58:28 0 ~/tmp] $ cat a
foobar
[23:58:50 0 ~/tmp] $ echo -n bar 1<>a
[23:58:53 0 ~/tmp] $ cat a
barbar
In what way is using > not useful? That explicitly does what you want by overwriting the file, so use > for the first and then >> to append future values.
echo "$var
$var1
$var2" > a.txt
or
echo -e "$var\n$var1\n$var2" > a.txt

Resources