So, I'm new to scripting, and I'm having some problems. The command I need to execute is:
read -p Enter_the_DEVICE_Bssid "device1" ;
read -p Enter_the_DEVICE_Bssid "device2" ;
read -p Enter_the_DEVICE_Bssid "device3"
That command works, but when I set it as a variable ie:
com="read -p Enter_the_DEVICE_Bssid "device1" ;
read -p Enter_the_DEVICE_Bssid "device2" ;
read -p Enter_the_DEVICE_Bssid "device3""
and execute it as: $com it does not work. Probably because the read command is trying to set my input to the variables device1 and ; .
Any ideas on how to fix it?
You're running into problems with the order in which things are expanded by the shell.
A simpler example:
$ command='echo one ; echo two'
$ $command
one ; echo two
The semicolon in the value of $command is taken as part of the argument to echo, not as a delimiter between two echo commands.
There might be a way to resolve this so it works the way you want, but why bother? Just define a shell function. Using my simple example:
$ command() { echo one ; echo two ; }
$ command
one
two
$
Or using yours:
com() {
read -p "Enter_the_DEVICE_Bssid: " device1
read -p "Enter_the_DEVICE_Bssid: " device2
read -p "Enter_the_DEVICE_Bssid: " device3
}
Note that I've added ": " at the end of the prompts. I've also removed the unnecessary semicolons and the quotation marks around the variable names (since the argument has to be a valid variable name, it doesn't need to be quoted).
You are not completing the quotes.
com="read -p Enter_the_DEVICE_Bssid "device1"
Quotes always look for a pair and you are missing that.
> com="read -p Enter_the_DEVICE_Bssid: device1"
> $com
Enter_the_DEVICE_Bssid:abc123
> echo $device1
abc123
Here I am using bash shell.
Related
#!/bin/bash
Dpath=/home/$USER/Docker/
IP=`sed -n 1p /home/medma/.medmadoc`
DockerMachine=`sed -n 2p /home/$USER/.medmadoc`
DockerPort=`sed -n 5p /home/$USER/.medmadoc`
DockerUser=`sed -n 3p /home/$USER/.medmadoc`
DockerPass=`sed -n 4p /home/$USER/.medmadoc`
if [ ! -d $Dpath ] ; then
mkdir -p $Dpath
else
stat=`wget -O ".dockerid" http://$IP/DOCKER-STAT.txt`
for ids in `cat .dockerid`
do
if [ "$ids" == "$DockerMachine" ] ; then
gnome-terminal -x sh -c 'sshfs -p$DockerPort $DockerUser#$IP:/var/www/html $Dpath ; bash '
nautilus $Dpath
zenity --info --text "Mounted $DockerMachine"
exit
else
:
fi
done
zenity --info --text "No Such ID:$DockerMachine"
fi
gnome-terminal -x sh -c 'sshfs -p$DockerPort $DockerUser#$IP:/var/www/html $Dpath ; bash '
this command opens up a new terminal but the problem is that it does not load vars like $DockerPort $DockerUser $IP $Dpath from this script.
How do I input the values in these vars from this script to the newly opened terminal ?
Thanks !
As indicated before, you could try to use double quotes instead of single quotes around the sshfs invocation.
Single quotes in Bash are used to delimit verbatim text, in which variables are not expanded. Double quotes, in contrast, allow for variables expansion and command substitution ($(...)) to take place.
If you do use double quotes, beware of unintended side-effects (your username may contain a space, a dollar, a semicolon, or any other shell-special character). A cleaner approach would be to export the variables to the environment before calling gnome-terminal (and not forgetting to add double quotes around your variables inside the single-quotes), so that your code looks like :
export Docker{Port,User} IP Dpath
gnome-terminal -x sh -c 'sshfs -p"$DockerPort" "$DockerUser#$IP":/var/www/html "$Dpath" ; bash'
You may not want to pollute the environment with variables that will only be used once. If that is the case, instead of exporting them, you can use Bash's declare -p feature to serialize variables before loading them into a new environment (in my opinion, this is the cleanest approach). Here is what it looks like :
set_vars="$(declare -p Docker{Port,User} IP Dpath)"
gnome-terminal -x bash -c "$set_vars;"'sshfs ....'
Using this latest method, the variables are only visible to the shell process that runs the sshfs command, not gnome-terminal itself nor any sub-process run thereafter.
PS: you could read all your variables at once from the ~/.medmadoc file by using the following code instead of repeated sed invocations :
for var in IP Docker{Machine,User,Pass,Port}; do
read $var
done < ~/.medmadoc
This code makes use of the read builtin, that reads a line of input into a variable (in its simplest form).
PPS: That stat variable probably won't contain any useful information, since the output of wget was redirected by the -O flag. Perhaps you meant to store the result code of wget into stat, in which case what you meant was :
wget -O .dockerid ...
stat=$?
created a simple shell file that contains this:
read -p ThePrompt TheSomthing
echo $TheSomething
Run it, and it returns
-ksh[1]: read: no query process
I've tried single quotes, double quotes around ThePrompt and the man page specifically says "-p" is to use a prompt but it is not working for me. Can anyone tell me what I'm doing wrong? Thanks!
In Ksh you can use this format:
echo "ThePrompt\c"
read TheSomthing
echo $TheSomething
From the googled man page:
The -un and -p options cause input to be read from file descriptor n or the current co-process (see Co-Processes above for comments on this), respectively. If the -s option is used, input is saved to the history file.
To use a prompt, write this instead:
read TheSomething?'ThePrompt'
I found a word around:
echo -n 'prompt: '
read input1
echo -n 'prompt: '
read input2
.
.
.
I don't know why the -p doesn't work as described in the man page. If anyone out there has insights, please reply.
Thanks!
Sorry for reviving this question, but I do my shell scripts in KSH, so I was in the same predicament, until I came with this.
My solution to capture a single character:
$> echo -e "My prompt: \c" ; read -n 1 -s -r FOO ; echo -e "\b"
My prompt:
$> echo $FOO
d
$>
For a longer string remove the "-n 1" from the read command:
$> echo -e "My prompt: \c" ; read -s -r FOO ; echo -e "\b"
My prompt:
$> echo $FOO
this is my entry!!!
$>
I hope this is what you were looking for... Cheers!
I have a Bash script that calls another Bash script. The called script does some modification and checking on a few things, shifts, and then passes the rest of the caller's command line through.
In the called script, I have verified that I have everything managed and ready to call. Here's some debug-style code I've put in:
echo $SVN $command $# > /tmp/shimcmd
bash /tmp/shimcmd
$SVN $command $#
Now, in /tmp/shimcmd you'll see:
svn commit --username=myuser --password=mypass --non-interactive --trust-server-cert -m "Auto Update autocommit Wed Apr 11 17:33:37 CDT 2012"
That is, the built command, all on one line, perfectly fine, including a -m "my string with spaces" portion.
It's perfect. And the "bash /tmp/shimcmd" execution of it works perfectly as well.
But of course I don't want this silly tmp file and such (only used it to debug). The problem is that calling the command directly, instead of via the shim file:
$SVN $command $#
results in the svn command itself NOT receiving the quoted string with spaces--it garbles the '-m "my string with spaces"' parameter and shanks the command as if it was passed as '-m my string with spaces'.
I have tried all manner of crazy escape methods to no avail. Can't believe it's dogging me this badly. Again, by echoing the very same thing ($SVN $command $#) to a file and then executing that file, it's FINE. But calling directly garbles the quoted string. That element alone shanks.
Any ideas?
Dan
Did you try:
eval "$SVN $command $#"
?
Here's a way to demonstrate the problem:
$ args='-m "foo bar"'
$ printf '<%s> ' $args
<-m> <"foo> <bar">
And here's a way to avoid it:
$ args=( -m "foo bar" )
$ printf '<%s> ' "${args[#]}"
<-m> <foo bar>
In this latter case, args is an array, not a quoted string.
Note, by the way, that it has to be "$#", not $#, to get this behavior (in which string-splitting is avoided in favor of respecting the array entries' boundaries).
this
echo -n -e $SVN \"$command\" > /tmp/shimcmd
for x in "$#"
do
a=$a" "\"$x\"
done
echo -e " " $a >> /tmp/shimcmd
bash /tmp/shimcmd
or simply
$SVN "$command" "$#"
Following the shell script that I am executing
#!/bin/sh
echo "Enter [y/n] : "
read opt
Its output is
Enter [y/n] :
Y
I want that the variable should be read on the same line like below
Enter [y/n] : Y
Should be simple I guess, but I am new to bash scripting.
Solution: read -p "Enter [y/n] : " opt
From help read:
-p prompt output the string PROMPT without a trailing newline before
attempting to read
The shebang #!/bin/sh means you're writing code for either the historical Bourne shell (still found on some systems like Solaris I think), or more likely, the standard shell language as defined by POSIX. This means that read -p and echo -n are both unreliable.
The standard/portable solution is:
printf 'Enter [y/n] : '
read -r opt
(The -r prevents the special treatment of \, since read normally accepts that as a line-continuation when it's at the end of a line.)
If you know that your script will be run on systems that have Bash, you can change the shebang to #!/bin/bash (or #!/usr/bin/env bash) and use all the fancy Bash features. (Many systems have /bin/sh symlinked to bash so it works either way, but relying on that is bad practice, and bash actually disables some of its own features when executed under the name sh.)
echo -n "Enter [y/n] : " ; read opt
OR! (Later is better)
read -p "[y/n]: " opt
use -n handle in echo, that will avoid trailing newline
echo -n "Enter [y/n] : "
read opt
I am having trouble running the script below (in Cygwin on win 7 mind you).
Lets call it "myscript.sh"
When I run it, the following is what I input:
yearmonth: 2011-03
daypattern: 2{5,6,7}
logfilename: error*
query: WARN
#! /bin/bash
yearmonth=''
daypattern=''
logfilename=''
sPath=''
q=''
echo -n "yearmonth: "
read yearmonth
echo -n "daypattern: "
read daypattern
echo -n "logfilename: "
read logfilename
echo -n "query: "
read q
cat "$yearmonth/$daypattern/$logfilename" | grep --color $q
The output I get is:
cat: /2011-03/2{5,6,7}/error* No such
directory of file exists.
However, if I enter daypattern=25 OR daypattern=26 etc. the script will work.
Also, of course if I type the command in the shell itself, the wildcards are expanded as expected.
But this is not what I want.
I want to be able to PROMPT the user to enter the expressions as they need, and then later, in the script, execute these commands.
Any ideas how this can be possible?
Your help is much appreciated.
Try eval, this should work for the {a,d} and * cases
eval grep --color $q ${yearmonth}/${daypattern}/${logfilename}
Use quote to prevent wildcard expansion:
$ a="*.py"
$ echo $a
google.py pair.py recipe-523047-1.py
$ echo "$a"
*.py