2

I use sed to change text in existing files and Nano to create new files.

I change text with sed this way, for example:

sudo sed -i 's/TESTING === "1"/TESTING === "0"/g' /etc/csf/csf.conf

Is there a way to create files with it, without going inside Nano or VI and pasting text, giving permission and then execute?

Usually I do cd ~ && nano script.sh && chmod +x script.sh && ./script.sh && rm -rf script.sh and then I paste all the script content inside, then save and execute.

This time however, I want to automate even that, and just paste everything as one input and run it in place.

In other words, I look for either a way to run the script from paste, or to paste it into a temporary file and run it "in-place" the moment I close the file and by that, to run it with the least number of clicks and pastings.


Why I need this solution:

The process can be repetitive when working with several server environments and I want to save time when doing this task time and again.

The discussion about the legitimacy of such action is surly a discussion by itself...


Here is an example --- I paste the following coomand to prompt (the first one, that includes ampersands), go into Nano to create the script and right then, I paste the following script syntax, save, and it it is being executed. I wish to automate this process as to do all of this, in one pasting / one action.

cd /home/testo && sudo nano script.sh && sudo chmod +x scripts.sh && sudo ./script.sh

#!/bin/bash -x

# Basic update and upgrade:
sudo apt-get update -y
sudo apt-get upgrade -y

# Setup CSF-LFD:
sudo rm -f csf.tgz
sudo wget https://download.configserver.com/csf.tgz
sudo tar -xzf csf.tgz
sudo sh install.sh
sudo perl /etc/csf/csftest.pl
sudo sed -i 's/TESTING === "1"/TESTING === "0"/g' /etc/csf/csf.conf
sudo csf -r
  • Please don't post images of text. It makes it hard to read, we can't copy and paste it, the text isn't picked up by Google for searches, it makes the question take longer to load, etc. etc. – Zachary Brady Nov 1 '16 at 12:29
  • Okay... No problem. Thank you for noting that! – JohnDoea Nov 1 '16 at 12:30
  • I deleted my answer because I misunderstood your question. – Zachary Brady Nov 1 '16 at 14:15
  • 3
    Yes, you can create files with sed but why would you want to use sed ? Have you ever heard of heredocs ? – don_crissti Nov 1 '16 at 14:24
  • Not very much more than the term itself. If this can use me for executing a copied script directly from paste then it should be useful... – JohnDoea Nov 1 '16 at 15:09
3
+100

In other words, I look for either a way to run the script from paste, or to paste it into a temporary file and run it "in-place" without saving any file --- To run everything is least number of clicks and pastings.

Assuming your interactive shell is a Bash or compatible shell -- you are looking for that :

bash << 'EOT'

<PASTE SCRIPT HERE>

EOT

The above code practice is called "Heredoc" (abbrivation of "Here document"), and I used it to execute all commands until EOT in a new sub-shell.

That way, you can change the working directory or alter environment. Notice EOT is not a keyword, so you can use whatever phrase you want instead of EOT (Just ensure the spelling is the same both at the start and end of the heredoc).

Single quotes are around 'EOT'are used to instruct the parent shell to not perform any substitution in the heredocument. This prevent for example variable expansion by the parent shell instead of the child shell.

As a concrete example:

sylvain@bulbizarre:~$ bash << 'EOT'
echo hello
cd /
echo We are in ${PWD}
EOT

hello
We are in /
sylvain@bulbizarre:~$   # <-- I'm still in my home directory when
                        #     back to the interactive shell

In other words, I look for either a way to run the script from paste, or to paste it into a temporary file and run it "in-place" without saving any file --- To run everything is least number of clicks and pastings.

If you want to keep a copy of the command executed, you may use that variation:

sylvain@bulbizarre:~$ tee /tmp/saved.sh << 'EOT' | bash
echo hello
cd /
echo We are in ${PWD}
EOT

hello
We are in /

sylvain@bulbizarre:~$ cat /tmp/saved.sh 
echo hello
cd /
echo We are in ${PWD}
  • 1
    This can be useful for me; Is there a special syntax if you want to include a script that already includes several EOFs inside one big EOF? – JohnDoea Nov 15 '16 at 21:51
  • 3
    @Benia EOT is not a keyword. You can use whatever you want. Some people use a single dot -- maybe in homage to the SMTP protocol ? – Sylvain Leroux Nov 15 '16 at 21:56
  • 4
    Just use different strings like EOF1 or pink_banana, as long as each nested pair is unique. – icarus Nov 15 '16 at 21:58
  • @SylvainLeroux, can you please elaborate what you mean in "I used it to execute all commands until EOT in a new sub-shell" as well as in "Single quotes are around 'EOT'are used to instruct the parent shell to not perform any substitution in the heredocument." ? I am not sure I understand, thanks for everything!!! – JohnDoea Nov 16 '16 at 2:11
  • 1
    @Benia Potentially, your script could contain 'cd' or expansion ($XYZ). If you run that script directly in your interactive shell like suggested here, you will alter that environment. Running in a sub-shell seems a safer approach. As about quotes, as you type the heredoc in the parent shell but want to execute it in the child shell, there is two shells that can perform expansion, say of variables. Without the single quotes, expansion is performed in the parent shell before sending the commands to the child shell. You may want that or not... – Sylvain Leroux Nov 16 '16 at 9:48
1

You can do this by prefixing to the script you want to paste:

echo '

and then suffixing a line thus:

'|sudo tee ses.sh >/dev/null && sudo chmod +x ses.sh && sudo ./ses.sh

and then you can copy'n'paste this whole thing in one go at the command line. For instance:

echo '#!/bin/bash
echo "Do some stuff - line 1"
echo "Do some stuff - line 2"
sudo echo -e "Do some stuff - line 3\nand line 4"
[[ 1 == 1 ]] && echo "We are all done here, bye!"
'|sudo tee ses.sh >/dev/null && sudo chmod +x ses.sh && sudo ./ses.sh

This will get thrown if the script you are pasting includes any single quotes, unfortunately.

Another way to do it that doesn't actually save a file is this:

/bin/bash -c '[script here]'

i.e. prefix /bin/bash -c ' and suffix a single '

Whether it is really advisable to be copy'n'pasting sudo scripts in this way is another question...

  • According to your answer I type in prompt: "/bin/bash -c ' " (without double quote marks) and then just copy and paste my script... I didn't add a single quote mark in the end of the script (I use only one single quote mark as in /bin/bash -c ')... Do you think it's okay? – JohnDoea Nov 3 '16 at 8:53
  • @Benia you need to add the single quote at the end of the script too so that the entire text between the two single quotes is treated as an argument to the -c parameter – gogoud Nov 3 '16 at 14:52
  • It ran without it... I must note... – JohnDoea Nov 3 '16 at 17:50
  • I now offer bounty. Please note that if I run echo ', and then '|sudo tee ses.sh >/dev/null && sudo chmod +x ses.sh && sudo ./ses.sh --- I don't get any text-editor like program to paste the script in run it in, and the regular bash re appears... Also note that if I just teyp echo ', then the script, and then '|sudo tee ses.sh >/dev/null && sudo chmod +x ses.sh && sudo ./ses.sh --- The script still won't run. – JohnDoea Nov 10 '16 at 23:37
  • Would appreciate your take on this, gogoud. – JohnDoea Nov 15 '16 at 18:45
1

In other words, I look for either a way to run the script from paste, or to paste it into a temporary file and run it "in-place" without saving any file --- To run everything is least number of clicks and pastings.

You can do exactly this using the "readline" library of your shell.

See LESS='+/^READLINE' man bash and also LESS='+/edit-and-execute-command' man bash.


For your case it is simple:

In your ~/.bashrc file, put the following line:

EDITOR=nano

Log out and log in again so the change takes effect. (Or just type . ~/.bashrc)

Then, when you want to paste in a command, type CtrlXCtrlE.

A temporary Nano buffer will be opened. Paste in (or type in) the commands you want to run.

When you save and exit, whatever you entered will be executed exactly as though you typed it in at the Bash command prompt.


If you start typing a command and then realize it is going to be long and you want the power of your editor to edit it, you can type CtrlXCtrlE at any time to edit the current command line using Nano.

Not that Nano has much power. Perhaps you should try learning Vim? :)

Again, see LESS='+/edit-and-execute-command' man bash for authoritative details.


Note that if you include an exit command, your shell will be exited. You're not running the commands as a script. You're running them in your current shell. So don't include an exit statement unless you want the same effect you would get by typing exit into your command prompt.

0

There seem to be no need to involve sed (or any other utility) as Bash can do it by itself:

I now note that it is enough for me to do: \ and afterwards, in the "row continuation prompt", that's opened up, I could just paste my script and it would run. For example:

\

> Paste your script here (with #!/bin/bash) and it would run directly.

Note:

You could run a script without a backslash () and with just typing the script inside but in case you have a script note (#) in the start that you copy the script with --- You would want to use a backslash.

Update:

Please read the comments: This answer might not be useful in some systems if your script includes comments.

  • 1
    You don't need even the backslash - you can paste the commands in directly at the command line and they will run ok. But they are running directly in the current shell and not in a separate process, and of course you don't have a saved executable file. – gogoud Nov 4 '16 at 7:26
  • Oh, haha, I thought I will must have a double-ampersands or semicolons there, one after each command. But indeed, it runs just as you noted, without ampersands or semicolons, and without a backsalsh. As I'm new, I can't explain how this is possible without ampersands or semicolons... – JohnDoea Nov 4 '16 at 15:19
  • If you run a command which attempts to read from standard in, you will likely see it "eat" the rest of the commands you typed in. Pasting multiple lines at once will work okay, it just runs each command, one by one. My answer is probably what you were looking for. – Wildcard Nov 6 '16 at 7:12
  • Right, why not simply paste the script right into the shell itself? Of course, if any errors exist in the script (such as syntax errors), you'll end up with the shell continuing on to run the subsequent commands and ignoring the error, but that would happen in a script file too without the appropriate settings (such as set -e). – ash Nov 14 '16 at 4:27
  • I now note my method here is problematic as some comments can brake execution (or thus it seemed to me last time I tried to run the script). – JohnDoea Nov 15 '16 at 18:49
0

If your goal is to run scripts that do not exist on remote machines: there are better ways to achieve it without having to copy paste the entire script on to the remote machine's terminal.

For example: You can execute a local script on a remote machine through ssh:

cat script.sh | ssh me@myserver /bin/bash

Edit: Thanks for taking the time to edit in additional information to your question so that it would no longer be an xyproblem Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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