I needed to write a script to enter multi-line input to a program (psql
).
After a bit of googling, I found the following syntax works:
cat << EOF | psql ---params
BEGIN;
`pg_dump ----something`
update table .... statement ...;
END;
EOF
This correctly constructs the multi-line string (from BEGIN;
to END;
, inclusive) and pipes it as an input to psql
.
But I have no idea how/why it works, can some one please explain?
I'm referring mainly to cat << EOF
, I know >
outputs to a file, >>
appends to a file, <
reads input from file.
What does <<
exactly do?
And is there a man page for it?
This operator stands for the end of the file. This means that wherever a compiler or an interpreter encounters this operator, it will receive an indication that the file it was reading has ended.
Cat is short for concatenate. This command displays the contents of one or more files without having to open the file for editing. In this article, learn how to use the cat command in Linux. A system running Linux. Access to a terminal window / command line.
head is used to print the first ten lines (by default) or any other amount specified of a file or files. cat , on the other hand, is used to read a file sequentially and print it to the standard output (that is, it prints out the entire contents of the file).
The cat <<EOF
syntax is very useful when working with multi-line text in Bash, eg. when assigning multi-line string to a shell variable, file or a pipe.
cat <<EOF
syntax usage in Bash:$ sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)
The $sql
variable now holds the new-line characters too. You can verify with echo -e "$sql"
.
$ cat <<EOF > print.sh
#!/bin/bash
echo \$PWD
echo $PWD
EOF
The print.sh
file now contains:
#!/bin/bash
echo $PWD
echo /home/user
$ cat <<EOF | grep 'b' | tee b.txt
foo
bar
baz
EOF
The b.txt
file contains bar
and baz
lines. The same output is printed to stdout
.
This is called heredoc format to provide a string into stdin. See https://en.wikipedia.org/wiki/Here_document#Unix_shells for more details.
From man bash
:
Here Documents
This type of redirection instructs the shell to read input from the current source until a line containing only word (with no trailing blanks) is seen.
All of the lines read up to that point are then used as the standard input for a command.
The format of here-documents is:
<<[-]word here-document delimiter
No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter case, the character sequence
\<newline>
is ignored, and\
must be used to quote the characters\
,$
, and`
.If the redirection operator is
<<-
, then all leading tab characters are stripped from input lines and the line containing delimiter. This allows here-documents within shell scripts to be indented in a natural fashion.
In your case, "EOF" is known as a "Here Tag". Basically <<Here
tells the shell that you are going to enter a multiline string until the "tag" Here
. You can name this tag as you want, it's often EOF
or STOP
.
Some rules about the Here tags:
example:
$ cat >> test <<HERE
> Hello world HERE <-- Not by itself on a separate line -> not considered end of string
> This is a test
> HERE <-- Leading space, so not considered end of string
> and a new line
> HERE <-- Now we have the end of the string
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With