How can I check if 'grep' doesn't have any output? - bash

I need to check if the recipient username is in file /etc/passwd which contains all the users in my class, but I have tried a few different combinations of if statements and grep without success. The best I could come up with is below, but I don't think it's working properly.
My logic behind it is that if the grep is null, the user is invalid.
send_email()
{
message=
address=
attachment=
validuser=1
until [ "$validuser" = "0" ]
do
echo "Enter the email address: "
read address
if [ -z grep $address /etc/passwd ]
then
validuser=0
else
validuser=1
fi
echo -n "Enter the subject of the message: "
read message
echo ""
echo "Enter the file you want to attach: "
read attachment
mail -s "$message" "$address"<"$attachment"
done
press_enter
}

Just do a simple if like this:
if grep -q $address /etc/passwd
then
echo "OK";
else
echo "NOT OK";
fi
The -q option is used here just to make grep quiet (don't output...)

Use getent and check for grep's exit code. Avoid using /etc/passwd. Equivalent in the shell:
getent passwd | grep -q valid_user
echo $?
Output:
0
And:
getent passwd | grep -q invalid_user
echo $?
Output:
1

Your piece of code:
if [ -z grep $address /etc/passwd ]
You haven't saved the results of grep $address /etc/passwd in a variable. Before putting it in the if statement and then testing the variable to see if it is empty.
You can try it like this:
check_address=`grep $address /etc/passwd`
if [ -z "$check_address" ]
then
validuser=0
else
validuser=1
fi

The -z check is for variable strings, which your grep isn't giving. To give a value from your grep command, enclose it in $():
if [ -z $(grep $address /etc/passwd) ]

The easiest one will be this:
cat test123
# Output: 12345678
cat test123 | grep 123 >/dev/null && echo "grep result exist" || echo "grep result doesn't exist"
# Output: grep result exist
cat test123 | grep 999 >/dev/null && echo "grep result exist" || echo "grep result doesn't exist"
# Output: grep result doesn't exist

My problem was that the file I was trying to grep was a binary file. On windows, the first two characters in the file were little squares. On mac, the first two characters were question marks. When I used more or less on the file, I could see it was binary and when I used diff, it responded that the "Binary files foo.log and requirements.txt differ".
I used cat to display the contents of the file, highlighted and copied the text (minus the two question marks at the top, deleted the file, created a new file with touch and then used vi to paste the text back into the new file.
After that, grep worked fine.

Shorter:
until ! grep $address /etc/passwd ; do {
do_your_stuff
}

Related

finding the string within folder using shell command

How to find all files within folder containing specific text (string) if text found return 1 if not return 0 in linux?
grep -r "34161FA8203289722240CD40" /usr/lib/cgi-bin/ParkingSoft/api/v3/LaneApi/ETC/MywebSocket /*.txt
Try This:
grep -rwl 'PATH/targetFolder/' -e 'target_string' | awk -F "/" '{print $NF}'
The above command returns the name of all files that contains the target_string.
To know about -rwl check this answer, However awk -F "/" '{print $NF}' just split the grep output and return the last part. (file name in your case)
The -q option returns (exit code) 1 when no match is found. Try:
echo "string" | grep -q in && echo yes
echo "string" | grep -q out && echo yes
In your case:
searchdir="/usr/lib/cgi-bin/ParkingSoft/api/v3/LaneApi/ETC/MywebSocket "
if [ ! -d "$searchdir" ]; then
echo "Check searchdir. Is 'ETC' really in uppercase and is `Mywebsocket ` including a space?"
else
if grep -rwq '34161FA8203289722240CD40' "${searchdir}/*.txt; then
echo "String found in one of the files."
fi
fi

Two "if" conditions in the same time

I am writing a script to bring me data from other nodes via ssh in a multi selection choice menu, and i want to display a message according to this data.
if [[ "$option" == "1" ]]
then
ssh skyusr#<IP> "export JAVA_HOME=/opt/mesosphere && /var/lib/mesos/slave/slaves/*/frameworks/*/executors/*/runs/latest/apache-cassandra-3.0.10/bin/nodetool -p 7199 status" | sed -n '6,10p' | awk '{print $1,$2}' | grep DN > $file_name
if [ -s $file_name ]
then
echo "All Cassandra Nodes are UP !"
else cat "$file_name"
fi
fi
When i execute the script, i see it does not see the second if condition to display the message .
What is the correct syntax ?
There is, as far as I can see, nothing wrong with the syntax. You might want to do something about spacing etc. to enhance readability, but that is it.
I assumed, that file_name is set somewhere before this part, as is option.
If things do not work as you expect them to work, you can add some statements for debugging purposes, which you must remove later on. For example, in this case, I would like to see the output of the ssh and add some echo's to see the flow-control:
if [[ "$option" == "1" ]] ; then
ssh skyusr#<IP> "export JAVA_HOME=/opt/mesosphere && /var/lib/mesos/slave/slaves/*/frameworks/*/executors/*/runs/latest/apache-cassandra-3.0.10/bin/nodetool -p 7199 status" > tempfile
cat tempfile |
sed -n '6,10p' |
awk '{print $1,$2}' |
grep DN > "$file_name"
if [ -s "$file_name" ] ; then
echo "All Cassandra Nodes are UP !"
else
echo "$file_name is not empty"
cat "$file_name"
fi
fi
You can use the tempfile to verify that your sed, awk, grep combination acts correctly.

How to match a folder name and use it in an if condition using grep in bash?

for d in */ ; do
cd $d
NUM = $(echo ${PWD##*/} | grep -q "*abc*");
if [[ "$NUM" -ne "0" ]]; then
pwd
fi
cd ..
done
Here I'm trying to match a folder name to some substring 'abc' in the name of the folder and check if the output of the grep is not 0. But it gives me an error which reads that NUM: command not found
An error was addressed in comments.
NUM = $(echo ${PWD##*/} | grep -q "*abc*"); should be NUM=$(echo ${PWD##*/} | grep -q "*abc*");.
To clarify, the core problem would be to be able to match current directory name to a pattern.
You can probably simply the code to just
if grep -q "*abc*" <<< "${PWD##*/}" 2>/dev/null; then
echo "$PWD"
# Your rest of the code goes here
fi
You can use the exit code of the grep directly in a if-conditional without using a temporary variable here ($NUM here). The condition will pass if grep was able to find a match. The here-string <<<, will pass the input to grep similar to echo with a pipeline. The part 2>/dev/null is to just suppress any errors (stderr - file descriptor 2) if grep throws!
As an additional requirement asked by OP, to negate the conditional check just do
if ! grep -q "*abc*" <<< "${PWD##*/}" 2>/dev/null; then

In a unix box, I am taking a list of files as input. If it is found, return the path otherwise return a message "filename file not found"

I have used the find command for this, but it doesnt return any message when a file is not found.
And I want the search to be recursive and return a message "not found" when a file is not found.
Here's the code I have done so far. Here "input.txt" contains the list of files to be searched.
set `cat input.txt`
echo $#
for i in $#
do
find $HOME -name $i
done
Try this:
listfile=input.txt
exec 3>&1
find | \
grep -f <( sed 's|.*|/&$|' "$listfile" ) | \
tee /dev/fd/3 | \
sed 's|.*/\([^/]*\)$|\1|' | \
grep -v -f - "$listfile" | \
sed 's/$/ Not found/'
exec 3>&-
open file descriptor 3
find the files
see if they're on the list (use sed to
send a copy of the found ones to file descriptor 3
strip off the directory name
get a list of the ones that don't appear
add the "Not found" message
close file descriptor 3
Output looks like:
/path/to/file1
/path/somewhere/file2
foo Not found
bar Not found
No loops necessary.
Whats wrong with using a script. I hope this will do.
#!/bin/bash -f
for i in $#
do
var=`find $HOME -name $i`
if [ -z "$var"]
then
var="File not found"
fi
echo $var
done
You can use the shell builtin 'test' to test the existence of a file. There is also an alternative syntax using square brackets:
if [ -f $a ]; then # Don't forget the semicolon.
echo $a
else
echo 'Not Found'
fi
Here is one way - create a list of all the files to grep against. If your implementation supports
grep -q otherwise use grep [pattern] 2&>1 >/dev/null....
find $HOME -type f |
while read fname
do
echo "$(basename $fname) $fname"
done > /tmp/chk.lis
while read fname
do
grep -q "^$fname" /tmp/chk.lis
[ $? -eq 0 ] && echo "$fname found" || echo "$fname not found"
done < /tmp/chk.lis
All of this is needed because POSIX find does not return an error when a file is not found
perl -nlE'say-f$_?$_:"not found: $_"' file

How to search an expression in a file from a bash script?

I have a bash script.
I need to look if "text" exists in the file and do something if it exists.
If you need to execute a command on all files containing the text, you can combine grep with xargs. For example, this would remove all files containing "yourtext":
grep -l "yourtext" * | xargs rm
To search a single file, use if grep ...
if grep -q "yourtext" yourfile ; then
# Found
fi
Something like the following would do what you need.
grep -w "text" file > /dev/null
if [ $? -eq 0 ]; then
#Do something
else
#Do something else
fi
grep is your friend here
You can put the grep inside the if statement, and you can use the -q flag to silence it.
if grep -q "text" file; then
:
else
:
fi
cat <file> | grep <"text"> and check the return code with test $?
Check out the excellent:
Advanced Bash-Scripting Guide
just use the shell
while read -r line
do
case "$line" in
*text* )
echo "do something here"
;;
* ) echo "text not found"
esac
done <"file"

Resources