0

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.

1 Answers1

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.

mikeserv
  • 58,310