How to store the output of command "which" in a variable in a bash script? - bash

Environment:
Mac OS Catalina 10.15
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19)
Problem:
I have a bash script.
I try to test if MacPOrt is installed.
When I run the command "port -v", it open Macport terminal and the rest of my script is broken.
So I try another approach with the command "which port".
It gives the output "port not found" but I don't succeed to store it in a variable. My variable is empty.
You can see here below the source code of my bash script executing 2 commands:
The first one give an empty value.
The second one give a value if Macport is not installed. But if it is installed, it open the Macport terminal and break my code.
OUTPUT=$(which port 2>&1)
echo "OUTPUT is $OUTPUT"
if echo "$OUTPUT" | grep -q "port not found"; then
echo "MacPort is NOT installed"
else
echo "MacPort is installed"
fi
echo "======================================================================"
OUTPUT=$(port -v 2>&1)
echo "OUTPUT is $OUTPUT"
if echo "$OUTPUT" | grep -q "command not found"; then
echo "MacPort is NOT installed"
else
echo "MacPort is installed"
fi
Here is the output:
OUTPUT is
MacPort is installed
======================================================================
OUTPUT is test.sh: line 11: port: command not found
MacPort is NOT installed
So it seems 'which' command doesn't behave like other commands. How can I store the output of 'which' command?
If it is not possible, I am agree to accept any other trick to test of Macport is installed.

If what you're really looking for is just to check if the port command is available, the right way to do it in bash would be:
if ! command -v port > /dev/null; then
echo "MacPort is not installed"
exit 1
fi

Your script has bugs:
OUTPUT=$(which port 2>&1)
echo "OUTPUT is $OUTPUT"
if echo "$OUTPUT" | grep -q "port not found"; then
echo "MacPort is NOT installed"
else
echo "MacPort is installed"
fi
You are checking for port not command. But which command doesn't actually output anything if port isn't found (whether which outputs anything differs on different systems). This is seen in your output (OUTPUT is empty).
In any case, you can't rely on which as it may not output anything
in some versions and even its return code isn't reliable on some old platforms.
A better approach is to use command or type built-ins of bash (This also avoids calling an external command like which):
if type port &>/dev/null; then
echo "MacPort is installed"
else
echo "MacPort is NOT installed"
fi
if command -v port &>/dev/null; then
echo "MacPort is installed"
else
echo "MacPort is NOT installed"
fi

Related

Write if condition in shell script and run command based on ubuntu version

Suppose for Ubuntu version 18 or less than that, i want to run command A else command B
How to do that?
You can get version form lsb_release command and then check if major version is less or equal -le to 18. If lsb_release is not avaiable in a system then just cat /etc/os-release and grep from it what is needed.
#!/bin/bash
OS_VER=$(lsb_release -sr | cut -d'.' -f1)
if [[ $OS_VER -le 18 ]]; then
echo "command 1"
else
echo "command 2"
fi
You can get the version of OS from any of these two file:
/etc/lsb_release
/etc/os-release
Then have an if/else command accordingly to check the version.

Previous command output on mac OS X

I have below script. When I run each line in iTerm on MacOs, every command works. But if i save this as a shell script, it says "!! command not found". I have tried #!/bin/bash. But still it doesn't work.
#!/bin/sh
./ongoingShellScript.sh
if !! | grep "errors: 0"
then
echo Success
else
echo Failure
fi
I could have done
if ./ongoingShellScript.sh | grep "errors: 0"
But in this case, output of ongoingShellScript won't be printed in realtime.
What am i doing here ?
Thank you in advance
GV
!! doesn't refer to previous output -- it runs the whole command over again, and thus generates a new set of output. Moreover, the featureset it comes from -- called "history expansion" -- is an interactive extension turned off by default during script execution.
If you want to print status for the user while testing stdout for a string, the easy tool for the job is grep:
if ./ongoingShellScript.sh | tee /dev/stderr | grep -q "errors: 0"; then
echo "Success" >&2
else
echo "Failure" >&2
fi
...assuming that errors: 0 comes at the end of output, and thus that it's acceptable for tee to exit as soon as grep has seen this string.

How to output error in custom color in Vagrant provision script?

I want my Vagrant provision script to run some checks that will require user action if they're not satisfied. As easy as:
if [ ! -f /some/required/file ]; then
echo "[Error] Please do required stuff before provisioning"
exit
fi
But, as long as this is not a real error, I got the echo printed in green. I'd like my output to be red (or, a different color at least) to alert the user.
I tried:
echo "\033[31m[Error] Blah blah blah"
that works locally, but on Vagrant output the color code gets escaped and I got it echoed in green instead.
Is that possible?
This is happening because some tools write some of their messages to stderr, which Vagrant then interprets as an error and prints in red.
Not all terminals support ANSI colour codes and Vagrant don't take care of that. Said that, I won't suggest colorizing a word by sending it to stderr unless it is an error.
To achieve that you can simply:
echo "Your error message" > /dev/stderr
You need to use keep_color true then it works as intended;
config.vm.provision "shell", keep_color: true, inline: $echoes
$echoes = <<-ECHOES
echo "\e[32mPROVISIONING DONE\e[0m"
ECHOES
From https://www.vagrantup.com/docs/provisioning/shell.html
keep_color (boolean) - Vagrant automatically colors output in green and red depending on whether the output is from stdout or stderr. If this is true, Vagrant will not do this, allowing the native colors from the script to be outputted.
Vagrant commands runs by default with --no-color option. You could try to set color on with --color. The environmental variables for Vagrant are documented here.
Here is a bash script test.sh which should demonstrate how to output to stderr or stdout conditionally. This form is good for a command like [ / test or touch that does not return any stdout or stderr normally. This form is checking the exit status code of the command which is stored in $?.
test -f $1
if [ $? -eq 0 ]; then
echo "File exists: $1"
else
echo "File not found: $1"
fi
You can alternatively hard code your file path like your question shows:
file="/some/required/file"
test -f $file
if [ $? -eq 0 ]; then
echo "File exists: $file"
else
echo "File not found: $file"
fi
If you have output of the command, but its being sent to stderr rather than stdout and ending up in red in the Vagrant output, you can use the following forms to redirect the output to where you would expect it to be. This is good for commands like update-grub or wget.
wget
url='https://example.com/file'
out=$(wget --no-verbose $url 2>&1)
if [ $? -ne 0 ]; then
echo "$out" > /dev/stderr
else
echo "$out"
fi
update-grub
out=$(update-grub 2>&1)
if [ $? -ne 0 ]; then
echo "$out" > /dev/stderr
else
echo "$out"
fi
One Liners
wget
url='https://example.com/file'
out=$(wget --no-verbose $url 2>&1) && echo "$out" || echo "$out" > /dev/stderr
update-grub
out=$(update-grub 2>&1) && echo "$out" || echo "$out" > /dev/stderr

Bash Centos7 "which" command

I realize this might be a dumb question but I have a Centos-7 minimal server install and the "which" command does not exist or is missing.
I have a script that needs it and I cannot find out what the yum package is that installs it.
The code is below and is from a make file.
which grep > /dev/null 2> /dev/null
if test "$?" != "0"
then
echo "\"grep\" command not found."
echo "Installation is aborted."
exit 1
fi
Any help would be appreciated... this is difficult if not impossible to google
To find a package in CentOS, use yum whatprovides:
yum whatprovides *bin/which
In this particular case, the package is called which, so
yum install which
should pull it in.
Instead of which command you can use type command.
type grep > /dev/null 2> /dev/null
if test "$?" != "0"
then
echo "\"grep\" command not found."
echo "Installation is aborted."
exit 1
fi

Checking status of program

This always works if I just type:if [ ! "$(pgrep vlc)" ]; then echo not running; else echo running; fi in the command prompt, but as soon as I make it a script, give it chmod +x and run it I always get "running" as the output. Can someone give me a lead?
#!/bin/bash
export DISPLAY=:0
if [ ! "$(pgrep vlc)" ]; then echo not running; else echo running; fi
If the name of your script contains 'vlc', pgrep founds that script running and condition in if is false, even though real VLC is not running.
You could insert
echo "$(pgrep vlc)"
before the if stament
You can be more selective with your pgrep command. It's not necessary to use command substitution and brackets.
#!/bin/bash
export DISPLAY=:0
if ! pgrep -f "/path/to/vlc " >/dev/null; then echo not running; else echo running; fi
another option to avoid mixup with your own script is to use ps's '-C' flag
(I dont know how portable it is though)
if ps -C vlc > /dev/null ; then echo running; else echo not runing; fi

Resources