Bash Centos7 "which" command - bash

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

Related

Why doesn't testing exit status work when output is redirected?

I have been testing bash and found the following code:
#!/bin/bash
[[ `which pacman` ]] && echo pacman
[[ `which apt-get` ]] && echo apt-get
It will test what package manager is installed and echo it.
On some systems, a failed which command prints the error to stderr. I want to suppress all output from the which command.
So I came up with the following code:
#!/bin/bash
[[ `which pacman >/dev/null 2>&1` ]] && echo pacman
[[ `which apt-get >/dev/null 2>&1` ]] && echo apt-get
But this doesn't output anything. When I run each command on the command line like this:
which pacman >/dev/null 2>&1 && echo $?
On a system with pacman, it prints 0 which it should. The && also proves that the previous command succeeded.
So why doesn't the redirection code work like it does on the command line? What can I add to the script to make it work?
This is really confusing to me, as I have never had this type of problem before. Usually, any command that works on the command line should also work in a bash script, shouldn't it?
[[ ... ]] without a specified test runs [[ -n ... ]]. In this case, it tests whether the captured output is non-empty. But if you redirect everything to /dev/null, the output is indeed empty!
You don't need to capture the output. which should already return a non-zero status when it cannot find the file to execute.
which pacman &> /dev/null && echo pacman

Is there a way for me to get specific words from an output of a command in bash?

For example, when running the dpkg command,
dpkg -s autofs
I would get an output like
dpkg-query: package 'autofs' is not installed and no information is available
But I just want to get the
not installed
part so that I can further use it for my script. Is there a command that can help me with it?
First of all, the words not installed are locale specific, so it will fail with anything but English locales. It is also non-predictable because it is not a published API Application Programming Interface.
So, even with some precautions, do not use this:
LC_MESSAGES=C dpkg-query --status autofs 2>&1 | grep -o 'not installed'
Check the return status of the dpkg-query command instead:
#!/usr/bin/env sh
package='autofs'
if dpkg-query --status "$package" >/dev/null 2>&1; then
printf 'Package %s is installed!\n' "$package"
else
printf 'Package %s is not installed!\n' "$package"
fi

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

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

How to use dpkg in silent mode

I try to test if some packages are installed in my script before run it.
To do that by the dpkg command. This is my code :
dpkg -s dialog
dialogStatut=$?
if [ "$dialogStatut" -eq 1 ]; then
//Install package
fi
I would like to make dpkg in silent mode (without echo).
I have tried to put >&- 2>&- behind the command but if i do that the value is always 2 (if dialog is installed or not).
I have don't find solution in man dpkg.
What is the best way to do that?
You are looking for 2> /dev/null
if ! dpkg -s dialog 2> /dev/null; then
...
fi
Consider just exiting your script to let dialog be installed explicitly rather than making your script responsible for doing so.
I would do something like
dpkg -l dialog &>/dev/null || apt-get install dialog
The speciality with OR(||) if the first condition evaluates to true(ie an exit status of zero), then the second condition will not be evaluated.

not found error when insert #!/bin/sh

I started learning Linux shell scripting, when I was writing this script I got an error,
./my_script: 4: read: Illegal option -n
./my_script: 5: ./my_script: [[: not found
I found out its because #!/bin/sh line, i can still run the script without that line but it won't execute codes such as /n
#!/bin/sh
# Shell installer for gurb customizer. by Naveen Gamage.
OS=$(lsb_release -si)
ARCH=$(uname -m | sed 's/x86_//;s/i[3-6]86/32/')
VER=$(lsb_release -sr)
grabninstall() {
sudo add-apt-repository ppa:danielrichter2007/grub-customizer
sudo apt-get update
sudo apt-get install grub-customizer
}
echo "Installer for GRUB CUSTOMIZER\n"
echo "GURB CUSTOMIZER"
echo "A tool for editing and configuring boot menu (GRUB2/BURG).\n"
read -p "Do you want to install Grub Customizer for $OS ${VER} [$ARCH] ? (Y/n) " -n 1
if [[ $REPLY =~ ^[Yy]$ ]]
then
echo "The installer is downloading and installing GRUB Customizer!";
echo "This action may require your password.\n";
grabninstall
else
echo "user quit"
echo "Installation was unsuccessful."
fi
I'm doing this on Ubuntu 12.10.
and which sh gives this output
/bin/sh
any idea where i did wrong?
The problem is that you are using /bin/sh to run the script and on your system /bin/sh -> dash. This means that dash is executing your script. The dash shell does not support [[, but bash does. So you should change the first line in your script (called the Shebang) from #!/bin/sh to #!/bin/bash.
Alternatively, don't use [[ in your script. Only use features support by dash.
Also see this Ubuntu page on what constructs are not supported in dash.

Resources