0

This question already has an answer here:

I know the > and >> operators, > puts something into a file by deleting the old content, >> appends something onto the end of the file's content.

When I only use

cat > foo

I am able to write several lines into foo interactively until I hit ctrl+z, than it ends.

Now, if I add the append operator in the reverse order with some word of my choice

cat > foo << "wordofchoice"

I can do the same as in the first case, but this time a > prompt appears at the beginning of each line and I can not end the interactive input by ctrl+z but by typing "wordofchoice" (without the double quote signs).

Why is it so, what is the logic behind this expression, the << operator does not seem to have its meaning of appending something in here.

marked as duplicate by Michael Homer, steeldriver, Gilles command-line Mar 22 '15 at 0:48

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • What's you're referring to is heredoc syntax – Bratchley Mar 22 '15 at 0:22
  • One point is to be able to pick your own terminator rather than having it be implied that a particular character signifies EOF. In your example "wordofchoice" is unlikely to compose part of what you're trying to give the command and so bash knows if it sees you typing that, you actually are done giving it input. – Bratchley Mar 22 '15 at 0:24
  • Search for << in your shell's manual. – Gilles Mar 22 '15 at 0:48
  • By the way, Ctrl-Z does not stop it, it just sends it to the background. Use Ctrl+C to stop. – terdon Mar 22 '15 at 11:34
  • @terdon: Ctrl+C will work for simple things like cat > filename, but, in general, the right way to tell a program that's reading from the terminal/keyboard to stop is Ctrl+D — try both techniques with something like grep pattern > filename. – Scott Sep 11 '16 at 6:17
1
  • $PS2
    • Each time the user enters a \newline prior to completing a command line in an interactive shell, the value of this variable shall be subjected to parameter expansion and written to standard error. The default value is >.

You see the > because that is the default value for $PS2 - which is the prompt string the shell will print when it cannot properly delimit a command string that contains a newline.

Your command string cannot be delimited because you have not closed a quoted string:

  • The various quoting mechanisms are the escape character, single-quotes, and double-quotes. The here-document represents another form of quoting; see Here-Document.

The shell's parser tokenizes input as it reads it - line by line. You have sent it a \newline - which also means your terminal has just sent it a copy of the command so far - but it detects at least one open-ended quoted string - in other words an incomplete command - and so prompts you for the rest of it..

  • If the current character is \backslash, 'single-quote, or "double-quote and it is not quoted, it shall affect quoting for subsequent characters up to the end of the quoted text. The rules for quoting are as described in Quoting. During token recognition no substitutions shall be actually performed, and the result token shall contain exactly the characters that appear in the input (except for \newline> joining), unmodified, including any embedded or enclosing quotes or substitution operators, between the \'"quotation-mark and the end of the quoted text. The token shall not be delimited by the end of the quoted field.

The here-document is a special form of quoting in that it is also a redirection - the shell redirects your input as delimited by the open token <<heredoc_delimiter_string\n and the expected close token \nheredoc_delimiter_string\n to command <<start_here_document.

  • The here-document shall be treated as a single word that begins after the next \newline and continues until there is a line containing only the <<delimiter and a \newline, with no blank characters in between. Then the next here-document starts, if there is one. The format is as follows:

    [n]<<word here-document delimiter

The shell would behave similarly if you submitted any other shell token which implied a second to the shell's parser but handed it a newline before the end token. $PS2 will print for example, if you start a for loop without entering done before entering a \newline, or one of the other quotes already mentioned.

Another way to put a \newline in a command is to quote it with the terminal - you can usually literally quote the next input character with CTRL+V. If you do CTRL+V then CTRL+J (or \newline) you can typically enter a literal \newline into the command string without the terminal sending the shell a copy of your input immediately - because usually the terminal sends it line-by-line, but when you CTRL+V quote the newline delimiter the shell won't yet receive it and so won't prompt you for more input.

This does not imply, however, that the terminal quoted newline is also properly quoted for the shell - you'd need to do that with shell quotes as applicable - but it will prevent the command string being read, at least, until you're ready to submit it.

Not the answer you're looking for? Browse other questions tagged or ask your own question.