228

What does <<< mean? Here is an example:

$ sed 's/a/b/g' <<< "aaa"
bbb

Is it something general that works with more Linux commands?

It looks like it's feeding the sed program with the string aaa, but isn't << or < usually used for that?

  • 8
    it seems < is for passing file (or directory), << @ for passing multiple lines (similar to the banner command in [tag:cisco] switches; as terminated by a custom string @ in this case), and <<< to pass a string (instead of file). test them yourself with cat and you'll grasp it very quickly. –  Oct 05 '17 at 10:32

4 Answers4

294

Others have answered the basic question: What is it? (Answer: It's a here string.)

Let's look at why it's useful.

You can also feed a string to a command's stdin like this:

echo "$string" | command

However in Bash, introducing a pipe means the individual commands are run in subshells. Consider this:

echo "hello world" | read first second
echo $second $first

The output of the 2nd echo command prints just a single space. Whaaaa? What happened to my variables? Because the read command is in a pipeline, it is run in a subshell. It correctly reads 2 words from its stdin and assigns to the variables. But then the command completes, the subshell exits and the variables are lost.

Sometimes you can work around this with braces:

echo "hello world" | {
    read first second
    echo $second $first
}

That's OK if your need for the values is contained, but you still don't have those variables in the current shell of your script.

To remedy this confusing situation, use a here string:

read first second <<< "hello world"
echo $second $first

Ah, much better!

glenn jackman
  • 85,964
152

<<< denotes a here string.

$ cat <<< 'hi there'
hi there

It passes the word on the right to the standard input of the command on the left.


<< denotes a here document.

$ cat <<EOF
> hi
> there
> EOF
hi
there

EOF can be any word.

Here documents are commonly used in shell scripts to create whole files or to display long messages.

cat > some-file <<FILE
foo
bar
bar bar
foo foo
FILE

< passes the contents of a file to a command's standard input.

$ cat < /etc/fstab
/dev/sda2               /boot   ext4            nosuid,noexec,nodev,rw,noatime,nodiratime       0 2
/dev/sda4               /       ext4            rw,noatime,nodiratime,  0 1
/dev/sdb5               /var    ext4            nosuid,noexec,nodev,rw,relatime 0 2
 ...
  • 10
    Is there a reason why someone would want cat < /etc/fstab instead of just cat /etc/fstab? Or is cat just a suboptimal example here? – Gerrit-K Jul 31 '18 at 07:06
  • In the first case, cat opens the file, and in the second case, the shell opens the file, passing it as cat's standard input. quote from https://unix.stackexchange.com/questions/258931/difference-between-cat-and-cat – star Apr 19 '19 at 00:53
  • 7
    I can't think of a reason why cat < file would ever be better than cat file. However, there are some cases where there is a difference -- for example, grep string file is different from grep string < file in that the second form doesn't prefix "file:" in front of every line. "cat file | grep string" is better written as "grep string < file". Not that any of this is worth doing for performance alone these days, but it is better coding practice. – Brian C Jul 09 '19 at 03:43
  • @star In cat < /etc/fstab, the shell opens the file, passing it as cat's standard input, whereas in cat /etc/fstab, cat opens the file. I think you'd interchanged them. – Ray Jasson Jun 05 '21 at 13:11
  • @BrianC cat < file > foo would not create or overwrite foo if file could not be opened and so wouldn't potentially zap a file in an error scenario while cat file > foo would create/overwrite foo in that case. – Ed Morton Dec 26 '21 at 14:09
  • Hi @ed-morton - In testing, cat < foo > file doesn't actually overwrite foo; and If there is an rare error reading the input file, cat foo is able to report the file name, whereas it cannot when presented with a stream via < file. Of course, BOTH forms are absolutely terrible shell programming practice and should never be done. Instead, use the cp command, or output to an intermediate file and use if [ -s foo.tmp ] to test for output file validity before then moving the output over the top of any existing file called foo. – Brian C Dec 27 '21 at 09:37
  • @BrianC I didn't suggest that cat < foo > file would overwrite foo, of course it doesn't. You misread my comment, it has nothing to do with overwriting the input file. I was providing a case where cat < file would be better than cat file in response to your comment "I can't think of a reason why cat < file would ever be better than cat file" – Ed Morton Dec 27 '21 at 12:18
21

Take a look at the Bash man page. This notation is part of what's called a here documents & here strings. It allows you the ability to generate multi-line data input as one continuous string. The variation you're asking about is called a here string.

excerpt from Bash man page

Here Strings
   A variant of here documents, the format is:
      &lt;&lt;&lt;word

The word is expanded and supplied to the command on its standard input.

NOTE: For more info you can also check out the Bash Reference Manual which discusses Here Strings.

slm
  • 369,824
9

It means here strings.

<<< strings

The strings is expanded and supplied to the command on its standard input.

In your example, strings aaa is feed to sed command via stdin.

cuonglm
  • 153,898