[SOLVED] Output missing and [: =: unexpected operator in script
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Output missing and [: =: unexpected operator in script
Hello everyone, I am trying to write a shell script that is in generic shel script NOT BASH. This shell script does one thing, mount drives. I got this idea from Luke Smith in this video he made: https://www.invidio.us/watch?v=YOpeXETS2z0, however I wanted something in generic script so I could use it on all my machines and something that did things a bit differently. After doing some research and reviewing how he did his I started on mine and wrote it out as I ran the commands in the shell. When I run the commands without variables and on their own everything works, but once I bring scripting into the picture it falls apart for some reason. I currently have this code
Code:
#!/bin/sh
# store all none mounted drives
drive=$(lsblk -lp | grep "part $" | awk '{print $1, "(" $4 ")"}')
if [ $drive = "" ]
then
exit 0
fi
# ask which drive to mount
chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
if [ $chosen = "" ]
then
exit 0
fi
# store mount directories in dirs
dirs=$(find /mnt/ /media/ -type d -maxdepth 3 2>/dev/null)
if [ $dirs = "" ]
then
exit 0
fi
mountpoint=$(echo "$dirs" | dmenu -i -p "Type in mount Point.")
if [ $mountpoint = "" ]
then
dmenu -i -p "$mountpoint does not exist"
fi
# mount drive to mountpoint
sudo mount $chosen $mountpoint && notify-send "$chosen mounted to $mountpoint."
and when I run this script there are issue, for example after
I apologize for posting once again here, I am just very new to shell scripting and honestly can't tell what the issue is. I did try to debug myself, but when I do everything works manually but not from a script. I want to fix these issues so I can add typing in sudo password to mount via dmenu then changing sudo to doas. Everything I can find through research is extremely BASH heavy and I honestly don't like shell specific scripts as it means it can't run on all my machines (OpenBSD has Ksh, Alpine has Ash and Mint has BASH).
still need to fix the issues with the '[' errors, but it works now
This has been solved, to see the solution for the '[' error there is a wonderful explanation below. The only other thing I can think of to ask here if anyone knows an equally efficient way to get the same info lsblk -lp gives using fdisk. I know I can use fdisk -l, but I also like the size info. If not that is fine, but I just like to test the tools I currently use for a task before adding a tool to my chain.
Couple of thoughts:
When you run from the command line, are you running as sh or bash?
Is set -x a bashism? Or will that work for sh scripts as well. If not, there's always the echo command to see what the script is seeing.
The error line number don't appear to line up with the script you've posted...that said, maybe quote the variables to control the interpolation of the contents?
And finally, I'm pretty sure all those OSs have a bash shell available...there's no requirement to use the "default" shell on any of them.
Couple of thoughts:
When you run from the command line, are you running as sh or bash?
Is set -x a bashism? Or will that work for sh scripts as well. If not, there's always the echo command to see what the script is seeing.
The error line number don't appear to line up with the script you've posted...that said, maybe quote the variables to control the interpolation of the contents?
And finally, I'm pretty sure all those OSs have a bash shell available...there's no requirement to use the "default" shell on any of them.
Oh, things like set -x aren't in my script that is all Luke's script. Mine only contains what I posted above, I did the ifs different to follow POSIX comp instead (for portability), this is running under sh not bash.
Oh, things like set -x aren't in my script that is all Luke's script. Mine only contains what I posted above, I did the ifs different to follow POSIX comp instead (for portability), this is running under sh not bash.
I saw that. I'm asking if set -x is POSIX compliant (I don't know) and if it is, then put it in to help you debug the script.
If it's not, then add some debugging echo statements to see what's going on.
Just trying to help...I don't personally have a concern about portability. All the systems I work on are the same. Just luck, I guess.
I saw that. I'm asking if set -x is POSIX compliant (I don't know) and if it is, then put it in to help you debug the script.
If it's not, then add some debugging echo statements to see what's going on.
Just trying to help...I don't personally have a concern about portability. All the systems I work on are the same. Just luck, I guess.
Ohhhh, my bad sorry about that. I'll check (as I don't know either) and use echos if not
set -x a is POSIX. I am stupid lol, when I was testing against Luke's verision I forget to use $drive not $mountable lol
#!/bin/sh
# store all none mounted drives
drive=$(lsblk -lp | grep "part $" | awk '{print $1, "(" $4 ")"}')
if [ $drive = "" ]
then
exit 0
fi
# ask which drive to mount
chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
if [ $chosen = "" ]
then
exit 0
fi
# store mount directories in dirs
dirs=$(find /mnt/ /media/ -type d -maxdepth 3 2>/dev/null)
if [ $dirs = "" ]
then
exit 0
fi
mountpoint=$(echo "$dirs" | dmenu -i -p "Type in mount Point.")
if [ $mountpoint = "" ]
then
dmenu -i -p "$mountpoint does not exist"
fi
# mount drive to mountpoint
sudo mount $chosen $mountpoint && notify-send "$chosen mounted to $mountpoint."
Line 6: if [ $drive = "" ]
$drive needs to be quoted, otherwise this expands to
if [ xxxx xxxx xxxx xxxx = "" ]
and that has multiple arguments to the left of the "=".
You have similar problems with all if the 'if [ $xxx = "" ]' statements. Quotes are needed around the "$xxx" or else a null or multi-word value causes a syntax error.
Line 14: chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
The mountable variable has not yet been set. (I see you've fixed that)
Last edited by rknichols; 06-16-2019 at 02:12 PM.
Reason: I see you've fixed ...
$drive needs to be quoted, otherwise this expands to
if [ xxxx xxxx xxxx xxxx = "" ]
and that has multiple arguments to the left of the "=".
You have similar problems with all if the 'if [ $xxx = "" ]' statements. Quotes are needed around the "$xxx" or else a null or multi-word value causes a syntax error.
Line 14: chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
The mountable variable has not yet been set. (I see you've fixed that)
Ohhhh, that makes sense; thank you so much for taking the time to explain it out as well. All fixed now, thank you so much!
$drive needs to be quoted, otherwise this expands to
if [ xxxx xxxx xxxx xxxx = "" ]
and that has multiple arguments to the left of the "=".
You have similar problems with all if the 'if [ $xxx = "" ]' statements. Quotes are needed around the "$xxx" or else a null or multi-word value causes a syntax error.
Line 14: chosen=$(echo "$mountable" | dmenu -i -p "Mount which drive?" | awk '{print $1}')
The mountable variable has not yet been set. (I see you've fixed that)
I hate to bug, but do you know how I would be able to put my password into dmenu and then have that be passed to sudo? In order to mount a drive I have to use sudo/doas and I would rather pass it via dmenu then disable a password for the account.
sudo reads the password directly from the TTY device and will not accept it from another source. That's to avoid unwise decisions like exposing your password in a script. I can't offhand think of a workaround that would not effectively allow passwordless mounting of any device on any directory.
I would suggest to add "set -eu" at the top of your script, where -e means it will exit on any error and -u means all unset variables are errors. I have learned that using this has improved the quality of my own scripts even if it is more work and should help in finding where in your code its failing.
However the only real good way of ensuring portability is to test many different shells, my current list of shells I test is ash, bash, dash, ksh, loksh, mksh, pdksh, posh, yash and zsh. Note that posh is inherently broken and zsh is not fully posix complaint, but is portable enough if extra care is taken.
I would suggest to add "set -eu" at the top of your script, where -e means it will exit on any error and -u means all unset variables are errors. I have learned that using this has improved the quality of my own scripts even if it is more work and should help in finding where in your code its failing.
However the only real good way of ensuring portability is to test many different shells, my current list of shells I test is ash, bash, dash, ksh, loksh, mksh, pdksh, posh, yash and zsh. Note that posh is inherently broken and zsh is not fully posix complaint, but is portable enough if extra care is taken.
Question, do you know how I would clear all the variables once this script finishes? I have found a way to do sudo via dmenu, but don't want to keep my password in a variable for security reasons.
After a script finishes any variables you set during the script will be gone. If you want to clear a variable before the script finishes you can always either overwrite it by setting it to a new value, turn it into a blank variable or unset it. Note that blank and unset variables are not the same thing.
If you want to set variables in your current environment from a script you have to source it instead of executing it.
Code:
# sourcing scripts
# note that using 'source' is not portable while using '.' is
. foo.sh
. bar.sh
# executing scripts
./foo.sh
sh foo.sh
From looking at your script I am failing to see where you password is being stored in a variable, when you type your password for sudo its not being recorded anywhere (Assuming no keylogger of course).
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.