5

Pasting some consecutive commands into terminal stops on commands with user input, e.g.:

read VAR
echo $VAR

or

select VAR in 1 2 3; do break; done
echo $VAR

echo $VAR is not getting pasted/executed.

Having all commands on a single line works though:

read VAR; echo $VAR

But this is not preferred when having more commands following.


Why is this the case and how to work around it ?

My use case is having some recurring commands in a service documentation.
I could of course write a script, but that is not what I intend to do and might not be possible on systems with read access only.

4
  • Don't paste shell code into the terminal, but put it into a script and run it as usual?
    – Kusalananda
    Jul 19, 2018 at 15:25
  • 2
    As I said that is not an option here.
    – pLumo
    Jul 19, 2018 at 15:27
  • Related security.stackexchange.com/questions/39118/…
    – JoL
    Jul 19, 2018 at 22:43
  • Thanks for the security related hints. I'm totally aware of it. For my use case I think it should be okay, as this is just a documentation for my own service for myself and the operator.
    – pLumo
    Jul 20, 2018 at 8:03

4 Answers 4

9

A very comfortable way is the following:

Just type the following in your terminal:

( paste-your-multiline-script-here ) enter

Long description:

  1. In the terminal you start with (

    Optional: Press enter (only for formatting reasons)

  2. Now you can paste multiple lines

    e.g.:
    echo hello
    echo world

    Alternative: You type/paste line by line (finishing each one with the enter key).

  3. Finally, type the finalizing ) and hit enter again, which will execute the whole pasted/entered lines.

Little working example (for pasting line by line with enter):

anderson@tp ~ % (
\`subsh> echo hello
\`subsh> echo world
\`subsh> )
hello
world
anderson@tp ~ % 

Little working example (for pasting whole script):

anderson@tp ~ % (
\`subsh> echo hello
echo world
\`subsh> )
hello
world
anderson@tp ~ %

Little working example neglecting formatting (for pasting whole script):

anderson@tp ~ % (echo hello                                                
echo world)
hello
world
anderson@tp ~ % 
6
  • 1
    This works. You don't even need to press enter, only at the end.
    – pLumo
    Jul 19, 2018 at 15:15
  • Yes, I've tried to make this clear. I will reformulate it in a better way. :) Happy pasting. ;)
    – Anderson
    Jul 19, 2018 at 15:16
  • 1
    It also works when pasting the whole thing: ( read VAR \n echo $VAR )
    – pLumo
    Jul 19, 2018 at 15:18
  • Of course, it was only for formatting reasons. :)
    – Anderson
    Jul 19, 2018 at 15:22
  • 2
    I mean paste including ( and ) works
    – pLumo
    Jul 19, 2018 at 15:23
6

When you paste the following two commands into a shell:

read VAR
echo $VAR

... the first one tells the shell to read a line of text into the variable named VAR. You provide that value on the next line; it just happens to be a command that you thought would be executed.

Print the value of the VAR variable and you'll see:

$ printf '%s\n' "$VAR"
echo $VAR

The same thing happens with the select menu.

I would suggest that if your documentation/commands expect the user to enter a value, you insert commentary to that effect:

read VAR

(User enters a value)

echo $VAR
1
  • Thanks for the explanation. Makes sense to me. What you mean by "insert commentary" ? Do you mean that I should tell the operator to copy-paste all commands until user input, and then copy-paste the rest ?
    – pLumo
    Jul 19, 2018 at 14:58
4

This can be done by putting \ at the end of each line before copying it.

1
  • 1
    adding ;\ indeed works. But it's quite annoying ...
    – pLumo
    Jul 19, 2018 at 14:53
2

You can get this work like you want exactly as you were doing it. I do this all the time.

If you were using zsh and a terminal that brackets its pastes with special escape sequences like urxvt, it would've already worked as you wanted by default. If you're using bash, you just need to activate its interpretation of paste brackets by doing bind 'set enable-bracketed-paste on'. It'll then wait for you to hit Enter before executing what you pasted. In this regard, the difference between bash and zsh is that bash will separate the commands you pasted in history, such that for 2 lines you'd need to hit Up, Up, Enter, Up, Up, Enter, while zsh keeps the commands pasted grouped as one in the history no matter how many lines, Up, Enter.

There's more of this written in the following answers. Second one's mine and includes a table of terminals that support bracketed-paste. If you do end up using urxvt, I recommend installing the extension I included in the answer to avoid the vulnerability that the question was about:

https://security.stackexchange.com/a/52655/132634

https://security.stackexchange.com/a/184112/132634

EDIT: By the way, just to be more explicit in case you missed it, if you're not doing this (using bracketed-paste), you're open to shell code injection when you're pasting from websites. Websites can, after all, hide code in all sorts of ways and have you copy it without your knowledge.

Check this site, to see if you're vulnerable:

http://thejh.net/misc/website-terminal-copy-paste

It looks like you'd be executing:

git clone git://git.kernel.org/pub/scm/utils/kup/kup.git

when in reality, you'd be running something like this (I removed a non-printable escape byte):

git clone [201~/dev/null; clear; echo -n "Hello ";whoami|tr -d '\n';echo -e '!\nThat was a bad idea. Don'"'"'t copy code from websites you don'"'"'t trust!
Here'"'"'s the first line of your /etc/passwd: ';head -n1 /etc/passwd
git clone git://git.kernel.org/pub/scm/utils/kup/kup.git 

You must log in to answer this question.

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