Bash Scripting - User Input a Command - bash

Very easy question but I really can't find this when I Google. Sorry!
I'm trying to write a script that runs a user's command that he or she enters but I can't run the command that the user enters.
#!/bin/bash
echo -e "Enter a Command: "
read $COMMAND
echo "Output: $COMMAND" # I can't figure how to implement and print the command
Enter a Command: ls
Output: folder1 folder2 folder3 test.txt)

All you need is to delete the dollar sign from the read command
#!/bin/bash
echo "Enter a Command: "
read COMMAND
echo "Output: $COMMAND"
Happy scripting!, please don't forget to marked as answered ;)

Use eval to execute a command from a variable.
Also, you don't put $ before the variable name in the read command. That's only used when you want to get the variable's value.
#!/bin/bash
echo -e "Enter a Command: "
read COMMAND
echo Output:
eval "$COMMAND"
DEMO

Thanks! This answered my question:
#!/bin/bash
echo -e "Enter a Command: "
read COMMAND
echo Output:
eval "$COMMAND"

Related

How do I programmatically execute a carriage return in bash?

My main file is main.sh:
cd a_folder
echo "executing another script"
source anotherscript.sh
cd ..
#some other operations.
anotherscript.sh:
pause(){
read -p "$*"
}
echo "enter a number: "
read number
#some operation
pause "Press enter to continue..."
I wanted to skip the pause command. But when I do:
echo "/n" | source anotherscript.sh
It doesn't allow to enter the number. I want the "/n" to occur so that I allow the user to enter a number but skip the pause statement.
PS: can't do any changes in anotherscript.sh. All changes to be done in main.sh.
Try
echo | source anotherscript.sh
Your approach does not work, because the script to be sourced expectes two lines from stdin: First a line containing a number, then an empty line (which is doing the pause). Hence you would have to feed two lines, the number and the empty line, to the script. If you still want to get the number from your own stdin, you would have to use a read command before:
echo "executing another script"
echo "enter a number: "
read number
printf "$number\n\n" | source anotherscript.sh
But this still has some danger lurking: The source command is executed in a subshell; hence, any changes in the environment performed by anotherscript.sh won't be visible in your shell.
A workaround would be to be to put the number-reading logic outside of main.sh:
# This is script supermain.sh
echo "executing another script"
echo "enter a number: "
read number
printf "$number\n\n"|bash main.sh
where in main.sh, you simply keep your source anotherscript.sh without any piping.
As user1934428 comments, the bash pipeline causes the cascading
commands to be executed in subshells and the variable modifications
there are not reflected in the current process.
To change this behavior, you can set lastpipe with shopt builtin.
Then bash changes the job control so that the last command in the
pipeline is executed in the current shell (as tsch does).
Then would you please try:
main_sh
#!/bin/bash
shopt -s lastpipe # this changes the job control
read -p "enter a number: " x # ask for the number in main_sh instead
cd a_folder
echo "executing another script"
echo "$x" | source anotherscript.sh > /dev/null
# anotherscript.sh is executed in the current process
# unnecessary messages are redirected to /dev/null
cd ..
echo "you entered $number" # check the result
#some other operations.
which will properly print the value of number.
Alternatively you can also say as:
#!/bin/bash
read -p "enter a number: " x
cd a_folder
echo "executing another script"
source anotherscript.sh <<< "$x" > /dev/null
cd ..
echo "you entered $number"
#some other operations.

Execute script to inside another bash script

On my server I try run:
#!/bin/bash
PATH="/SANCFS/stats/scripts/"
for (( i=6;i<=8;i++ ));
do
echo "Running $i"
exec "/SANCFS/stats/scripts/load_cdrs.sh --debug --config /SANCFS/stats/scripts/iquall-mm4-cdr.cfg --date '2018-10-0"$i"' >> /home/stats/201810/load_cdrsIMRMM4-0"$i".ok 2>>/home/stats/201810/load_cdrsIMRMM4-0"$i".err"
done
And the result is:
cannot execute: No such file or directory
Your help, how edit/modify to run successfully ?
Here's an easier way to reproduce your problem:
$ exec "echo "hello world""
bash: exec: echo hello: not found
Running a command in bash does not require adding exec or quotes:
$ echo "hello world"
hello world
Additionally, you are using $i in single quotes in one case, and you're overwriting the shell search path PATH for seemingly no reason. Applied to your example:
#!/bin/bash
for (( i=6;i<=8;i++ ));
do
echo "Running $i"
/SANCFS/stats/scripts/load_cdrs.sh --debug --config /SANCFS/stats/scripts/iquall-mm4-cdr.cfg --date "2018-10-0$i" >> /home/stats/201810/load_cdrsIMRMM4-0"$i".ok 2>>/home/stats/201810/load_cdrsIMRMM4-0"$i".err
done
Don't use exec. That replaces the current process with the process that runs the specified command, so you won't repeat the loop. Just execute the command normally.
And the argument to exec shouldn't be all inside a single quoted string. Maybe you're confusing it with eval?
#!/bin/bash
PATH="/SANCFS/stats/scripts/"
for (( i=6;i<=8;i++ ));
do
echo "Running $i"
/SANCFS/stats/scripts/load_cdrs.sh --debug --config /SANCFS/stats/scripts/iquall-mm4-cdr.cfg --date 2018-10-0"$i" >> /home/stats/201810/load_cdrsIMRMM4-0"$i".ok 2>>/home/stats/201810/load_cdrsIMRMM4-0"$i".err
done
You could replace exec with dot ( . )
If you try the 5 options, you should see the different options
$ exec /bin/bash
$ /bin/bash
$ . /bin/bash
$ ./bin/bash
$ /bin/bash /bin/bash

Redirect to a file which is got from command line

I'm a beginner. :)
I'm trying to ask the name of file from prompt in a shell
and edit that file in another shell like this:
test.sh
echo "enter file name"
read word
sh test2.sh
test2.sh
read number
echo "$number" >> $word
I get an error
Test2.sh: line 1: $mAmbiguous redirect
Any suggestion?
If you want a variable from test.sh to be visible to its child processes, you need to export it. In your case, you would seem to want to export word. Perhaps a better approach would be for test2.sh to accept the destination file as a parameter instead, though.
test.sh
echo "enter file name"
read word
test2.sh "$word"
test2.sh
#!/bin/sh
: ${1?must have destination file name} # fail if missing
read number
echo "$number" >> "$1"

SSH heredoc: bash prompt

I am attempting to write a shell script which SSHs into a server and then prompts the user to enter a file/folder.
ssh $SERVER <<EOF
cd downloads/
read -e -p "Enter the path to the file: " FILEPATH
echo $FILEPATH
eval FILEPATH="$FILEPATH"
echo "Downloading $FILEPATH to $CLIENT"
EOF
I am using heredoc instead of double quotes after the SSH to execute these commands because my shell script is rather large and I don't want to be escaping every double quote.
When I was using double quotes, the prompt worked fine. However, now that I am using heredoc, the prompt no longer works.
What can I do to get the prompt to work with heredoc? And if not, is there any way I layout my script so that the prompt does work without wrapping everything in double quotes and escaping, like so:
ssh $SERVER "
cd downloads/
read -e -p \"Enter the path to the file: \" FILEPATH
echo $FILEPATH
eval FILEPATH=\"$FILEPATH\"
echo \"Downloading $FILEPATH to $CLIENT\"
exit
"
If you don't need any variables from the client, why not try - and ssh -t might be useful.
export CLIENT=me
CMDS=$(cat <<CMD
cd downloads/
read -e -p "Enter the path to the file: " FILEPATH
echo \$FILEPATH
eval FILEPATH="\$FILEPATH"
echo "Downloading \$FILEPATH to $CLIENT"
CMD
)
ssh localhost -t "$CMDS"
Note that if your only issue with double-quotes is escaping, and you do not plan on
using ' single quotes in your script, then you can ust do this:
ssh -t $SERVER '
# your script, unescaped.
# if you want access to a locally defined variable,
echo "CLIENT is '$CLIENT'."
'
To make it work with a heredoc, it should be sufficient to invoke bash, or whatever shell you want to use on the remote server. Like so:
ssh $SERVER bash <<EOF
cd downloads/
read -e -p "Enter the path to the file: " FILEPATH
echo $FILEPATH
eval FILEPATH="$FILEPATH"
echo "Downloading $FILEPATH to $CLIENT"
EOF
Note that you probably want to escape the $ on FILEPATH, since currently that will be interpolated by the local shell rather than the remote shell.
this works, tab completion on the host works.
var=$(cat<<EOF
read -e -p Path pname;
echo \$pname;
hostname;
echo \$pname;
cd \$pname;
pwd;
touch THIS ;
exit;
EOF
)
ssh -t NODE $var
on mine this creates the file THIS in the prompted for directory.
This one seems to work:
T=$(tty) ; bash <<XXX
echo Hi "$T"
read p <$T
echo p: \$p
echo Bye
XXX

bash: problem running command with quotes

In answering another question I created the following script bash script:
#!/bin/bash
files1=( file1.txt file2.txt file3.txt )
files2=( file1_.txt file2_.txt file3_.txt )
cmd="vim -c 'set diffopt=filler,vertical' -c 'edit ${files1[0]}' -c 'diffsplit ${files2[0]}' "
echo $cmd
for i in {1..2}; do
cmd="${cmd} -c 'tabe ${files1[i]}' -c 'diffsplit ${files2[i]}' "
done
#$cmd
echo $cmd
the problem is that if I try to run
$cmd
in the end of the script I get errors, but if I just use echo $cmd and then copy and paste in the command line it works just fine.
Any ideas what I am doing wrong?
Thanks.
Use:
eval $cmd
So that the variables within the expression are expanded before execution.
BASH FAQ entry #50: "I'm trying to put a command in a variable, but the complex cases always fail!"

Resources