0

I tried to copy-paste the following two commands into the terminal directly and to then execute them:

read -s x
read -s y

Current output is empty prompt but desired output is the first read execution and then the second read execution.

I can overcome this with:

read -s x &&
read -s y

But;

Why two or more read commands cannot be executed in one go (without some separation syntax)?

2 Answers 2

5

By default, it doesn't make any difference to the terminal whether a <newline> character was part of some pasted text or typed by the user. When you paste

read -s x
read -s y

the <newline> after read -s x makes your terminal send that line to your shell. The shell parses it, finds it is a complete command end thus executes it: read then waits for content on standard input and the terminal feeds it with the line read -s y, which ends up set as the value of x.

It approximately works as if you typed read -s x, pressed Enter, typed read -s y, pressed Enter again.

Whether it needs an extra Enter on your part, what exactly the value of x becomes, what is actually printed out and what would happen to subsequent lines depends on your shell and the mode it sets the terminal to. For instance, using Bash 5.0 and assuming both the lines in the clipboard are terminated by a <newline>,

                        # Pasting with Ctrl + Shift + v, Enter
$ read -s x
$                       # The prompt comes back after pressing Enter again
$ declare -p x y
"eclare -- x="read -s y
bash: declare: y: not found

(declare's output looks mangled because Bash configures the terminal not to convert \r (carriage return) into \n (line feed) when line editing is active (the default); when the first read instructs the terminal to enable the \r\n conversion the terminal has already put a \r (the character it sends when Enter is pressed or a line feed is pasted) after the second pasted line into the buffer, causing read to add it literally to the value of x and to require you to press Enter to signal the end of the input).

This does not happen if you paste

read -s x &&
read -s y

because the shell parses read -s x && as an incomplete "AND" list and waits for more input until it can run a complete command.

The way you can paste several commands at once is by using "bracketed paste", a terminal mode in which pasted text is inserted in the buffer as a single string instead of being treated as if it had been manually typed.

Bash supports it since version 4.4. You can enable it by adding

set enable-bracketed-paste on

to the Readline initialization file (by default, ~/.inputrc).

Zsh supports it since version 5.1 and it is enabled by default when ZLE (Zsh Line Editor) is active.

See, for more details on how it works and how to enable it:

1

You'll need some sort of separation syntax otherwise how will it know where one read command ends and the next one begins?

Using && will only execute the second read if the first one did not return any errors. If you want the second one to always execute, you could use ; like this:

read -s x ; read -s y

But it's unclear to me if you want to execute one read and store it in the variable x, then execute a second read and store it in y or if you want to execute one read and store the same result in both x and y. My suggestion does the former.

1
  • how will it know where one read command ends and the next one begins? some shells might be built to separate these as Bash itself separates some commands from others (when copy-pasting and executing two or more in one go) ; I want that by read variable x holds value1 and variable y holds value2.
    – George
    Aug 27, 2020 at 18:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .