While file doesn't contain string BASH - bash

I am making a script for my school, and I was wondering how I could check a file, and if the string isn't in the file, do a code, but if it is, continue, like this:
while [ -z $(cat File.txt | grep "string" ) ] #Checking if file doesn't contain string
do
echo "No matching string!, trying again" #If it doesn't, run this code
done
echo "String matched!" #If it does, run this code

You can do something like:
$ if grep "string" file;then echo "found";else echo "not found"
To do a loop :
$ while ! grep "no" file;do echo "not found";sleep 2;done
$ echo "found"
But be carefull not to enter an infinite loop. string or file must be changed otherwise the loop has no meaning.
Above if/while works based on the return status of the command and not on the result.
if grep finds string in file will return 0 = success = true
if grep does not find string will return 1 = not success = false
By using ! we revert the "false" to "true" to keep the loop running since while loops on something as soon as it is true.
A more conventional while loop would be similar to your code but without the useless use of cat and the extra pipe:
$ while [ -z $(grep "no" a.txt) ];do echo "not found";sleep 2;done
$ echo "found"

A simple if statement to test if a 'string' is not in file.txt:
#!/bin/bash
if ! grep -q string file.txt; then
echo "string not found in file!"
else
echo "string found in file!"
fi
The -q option (--quiet, --silent) ensures output is not written to standard output.
A simple while loop to test is a 'string' is not in file.txt:
#!/bin/bash
while ! grep -q string file.txt; do
echo "string not found in file!"
done
echo "string found in file!"
Note: be aware of the possibility that the while loop may cause a infinite loop!

Another simple way is to just do the following:
[[ -z $(grep string file.file) ]] && echo "not found" || echo "found"
&& means AND - or execute the following command if the previous is true
|| means OR - or execute if the previous is false
[[ -z $(expansion) ]] means return true if the expansion output is null
This line is much like a double negative, basically:
"return true if the string is not found in file.file; then echo not found if true, or found if false"
Example:
bashPrompt:$ [[ -z $(grep stackOverflow scsi_reservations.sh) ]] && echo "not found" || echo "found"
not found
bashPrompt:$ [[ -z $(grep reservations scsi_reservations.sh) ]] && echo "not found" || echo "found"
found

Related

Setting a variable inside a conditional

Is it possible to set a variable from the output of a command inside of a conditional where the conditional is false if nothing gets assigned to the variable.
If I set the variable to a grep with no return and then test:
test=$(echo hello | grep 'helo')
if [[ ! -z $test ]]; then
echo "is set"
else
echo "not set"
fi
Output: not set (this is expected)
But I'm trying to put it all into one statement like this:
test=
if [[ ! -z test=$(echo hello | grep 'helo') ]]; then
echo "is set"
else
echo "not set"
fi
output: "is set" (expected not set)
grep returns success if there is a match, so you can just do:
if test=$(echo hello | grep 'helo')
then
echo "Match: $test"
else
echo "No match"
fi
If you're running something that doesn't differentiate by exit code, you can assign and check in two statements on the same line:
if var=$(cat) && [[ -n $var ]]
then
echo "You successfully piped in some data."
else
echo "Error or eof without data on stdin."
fi
(or ; instead of && if you want to inspect the result even when the command reports failure)
Bit of a hack, using the shell's parameter expansion alternate value syntax, echo -e and some backspaces:
test=$(echo hello | grep 'helo'); echo -e not${test:+\\b\\b\\bis} set
Which outputs is set or not set depending on what grep finds.

shell - var length with if condition gives error

I am trying to see if I found something using grep or not with this
found=`grep -F "something" somefile.txt`
if ((${#found} == 0)); then
echo "Not Found"
else
echo "Found"
fi
I succeeded using above logic that if grep found something it stores the output in found variable but the issue I am facing is with if condition. Whenever found=0 it gives me some error like that
final.sh: 13: final.sh: 0: not found
FYI: final.sh is the script name
The problem is that you're writing bash specific code, but running it with sh. In bash, (( .. )) is an arithmetic context, while in POSIX sh, it's merely two nested subshells, causing it to try to execute the number as a command.
You can run it with bash instead of sh by specifying #!/bin/bash in the shebang, and/or using bash yourfile instead of sh yourfile if you invoke it that way.
The correct way for your example, however, is to use grep's exit status directly:
if grep -q something somefile
then
echo "found"
else
echo "not found"
fi
To check whether some string is in your file, you can use the return status from grep
grep -q something somefile.txt
if [ $? -eq 0 ]
then
echo "found"
else
echo "not found"
fi
a shorter form will be
grep -q something somefile.txt && echo found || echo not found
found=$(grep -F "something" somefile.txt)
if [ $? = 0 ]; then # $? is the return status of a previous command. Grep will return 0 if it found something, and 1 if nothing was found.
echo "Something was found. Found=$found"
else
echo 'Nothing was found'
fi
I find this code more elegant than other answers.
But anyway, why are you writing in sh? Why don't you use bash? Are you sure that you need that portability? Check out this link to see if you really need sh
Here's how I do that sort of thing:
found=$(grep -F "something" somefile.txt)
if [[ -z $found ]]; then
echo "Not found"
else
echo "Found"
fi

bash determine if variable is empty and if so exit.

I am trying to perform this:
i have a test file which md5sum of files located on sftp.
variables should contain an md5sum (string), if the variable is empty it means there is no file on the sftp server.
i am trying this code but it does not work..
if [ -z $I_IDOCMD5 ] || [ -z $I_LEGALMD5 ] || [ -z $I_ZIPMD5 ]
then
echo "ERROR: At least one file not present of checksum missing no files will be deleted" >>$IN_LOG
ERRORS=$ERRORS+2
else
if [[ $I_IDOCMD5 == $($DIGEST -a md5 $SAPFOLDER/inward/idoc/$I_IDOC) ]]
then
echo "rm IDOC/$I_IDOC" >/SAP/commands_sftp.in
else
echo "problem with checksum"
ERRORS=$ERRORS+2
fi
if [[ $I_LEGALMD5 == $($DIGEST -a md5 $SAPFOLDER/inward/legal/$I_LEGAL) ]]
then
echo "rm LEGAL/$I_LEGAL" >>/SAP/commands_sftp.in
else
echo "problem with checksum"
ERRORS=$ERRORS+2
fi
if [[ $I_ZIPMD5 == $($DIGEST -a md5 $SAPFOLDER/inward/zip/$I_ZIP) ]]
then
echo "rm ZIP/$I_ZIP" >>/SAP/commands_sftp.in
else
echo "problem with checksum"
ERRORS=$ERRORS+2
fi
The answer I prefer is following
[[ -z "$1" ]] && { echo "Parameter 1 is empty" ; exit 1; }
Note, don't forget the ; into the {} after each instruction
One way to check if a variable is empty is:
if [ "$var" = "" ]; then
# $var is empty
fi
Another, shorter alternative is this:
[ "$var" ] || # var is empty
In bash you can use set -u which causes bash to exit on failed parameter expansion.
From bash man (section about set builtin):
-u
Treat unset variables and parameters other than the special parameters "#" and "*" as an error when performing parameter
expansion. If expansion is attempted on an unset variable or
parameter, the shell prints an error message, and, if not interactive,
exits with a non-zero status.
For more information I recommend this article:
http://redsymbol.net/articles/unofficial-bash-strict-mode/
You can use a short form:
FNAME="$I_IDOCMD5"
: ${FNAME:="$I_LEGALMD5"}
: ${FNAME:="$I_ZIPMD5"}
: ${FNAME:?"Usage: $0 filename"}
In this case the script will exit if neither of the I_... variables is declared, printing an error message prepended with the shell script line that triggered the message.
See more on this in abs-guide (search for «Example 10-7»).
First test only this (just to narrow it down):
if [ -z "$I_IDOCMD5" ] || [ -z "$I_LEGALMD5" ] || [ -z "$I_ZIPMD5" ]
then
echo "one is missing"
else
echo "everything OK"
fi
echo "\"$I_IDOCMD5\""
echo "\"$I_LEGALMD5\""
echo "\"$I_ZIPMD5\""
"if the variable is empty it means there is no file on the sftp server"
If there is no file on the sftp server, is the variable then really empty ?
No hidden spaces or anything like that ? or the number zero (which counts as non-empty) ?

From bash to ksh - script throws errors but still works

I have created a simple BASH script that checks every hour for the presence of a file on a remote server. It worked error-free until I was asked to move it to a server that runs KSH.
The portion of code that errors-out is this one:
connect_string=$UID#$SERVER:$srcdir/$EVENTFILE
result=`sftp -b "$connect_string" 2>&1`
if [ echo "$result" | grep "not found" ]; then
echo "not found"
else
echo "found"
fi
These are the errors it throws:
-ksh: .[51]: [: ']' missing
grep: ]: No such file or directory
found
It still runs though and confirms that the file I am polling for is there but I need to fix this. I changed the if statement like so
if [[ echo "$result" | grep "not found" ]]; then
but it fails right away with this error
-ksh: .: syntax error: `"$result"' unexpected
What am I missing?
Your basic syntax assumptions for if are incorrect. The old [...] syntax, calls the test builtin, and [[...]] is for textual pattern matching.
As #shelter's comment, the correct syntax is:
connect_string="$UID#$SERVER:$srcdir/$EVENTFILE"
result=`sftp -b "$connect_string" 2>&1`
if echo "$result" | grep "not found" ; then
echo "not found"
else
echo "found"
fi
But this is an unnecessary use of the external grep program, you can use shell text comparison:
if [[ $result == *not\ found* ]] ; then
echo "not found"
else
echo "found"
fi
(tested with bash and ksh)
Your solution:
EXIT=`echo $?`
if [ $EXIT != 0 ]
then
...
fi
Can be improved. First, if you are going to do an arithmetic comparison, then use ((...)), not test, and I can't figure out why you have the EXIT variable:
if (( $? != 0 ))
then
...
fi
But to go full circle, you actually only need:
if sftp -b "$connect_string" 2>&1
then
...
fi
echo "$result" | grep "not found"
#capture exit status code from previous command ie grep.
if [[ $? == 0 ]]
than
echo "not found"
else
echo "found"
fi
It appears you're struggling with a basic tenet of bash/ksh control structures.
Between the if and the then keywords, the shell expects one or more commands, with
the last command in the series deciding how the if statement is processed.
The square brackets are only needed if you actually need to perform a comparison. Internally they are equivalent to the test command - if the comparison succeeds, it
results in an exit status of 0.
Example:
$ [ a == a ]
$ echo $?
0
$ [ a == b ]
$ echo $?
1
Which is equivalent to:
$ test a == a
$ echo $?
0
$ test a == b
$ echo $?
1
I changed my approach to this.
connect_string=$UID#$SERVER:$srcdir/$EVENTFILE
result=`sftp "$connect_string" 2>&1`
EXIT=`echo $?`
if [ $EXIT != 0 ]
then
echo "file not found"
exit 1
else
echo "file found"
exit 0
fi
It takes care of my problem. Thanks to all.

How to check if a file contains a specific string using Bash

I want to check if a file contains a specific string or not in bash. I used this script, but it doesn't work:
if [[ 'grep 'SomeString' $File' ]];then
# Some Actions
fi
What's wrong in my code?
if grep -q SomeString "$File"; then
Some Actions # SomeString was found
fi
You don't need [[ ]] here. Just run the command directly. Add -q option when you don't need the string displayed when it was found.
The grep command returns 0 or 1 in the exit code depending on
the result of search. 0 if something was found; 1 otherwise.
$ echo hello | grep hi ; echo $?
1
$ echo hello | grep he ; echo $?
hello
0
$ echo hello | grep -q he ; echo $?
0
You can specify commands as an condition of if. If the command returns 0 in its exitcode that means that the condition is true; otherwise false.
$ if /bin/true; then echo that is true; fi
that is true
$ if /bin/false; then echo that is true; fi
$
As you can see you run here the programs directly. No additional [] or [[]].
In case if you want to check whether file does not contain a specific string, you can do it as follows.
if ! grep -q SomeString "$File"; then
Some Actions # SomeString was not found
fi
In addition to other answers, which told you how to do what you wanted, I try to explain what was wrong (which is what you wanted.
In Bash, if is to be followed with a command. If the exit code of this command is equal to 0, then the then part is executed, else the else part if any is executed.
You can do that with any command as explained in other answers: if /bin/true; then ...; fi
[[ is an internal bash command dedicated to some tests, like file existence, variable comparisons. Similarly [ is an external command (it is located typically in /usr/bin/[) that performs roughly the same tests but needs ] as a final argument, which is why ] must be padded with a space on the left, which is not the case with ]].
Here you needn't [[ nor [.
Another thing is the way you quote things. In bash, there is only one case where pairs of quotes do nest, it is "$(command "argument")". But in 'grep 'SomeString' $File' you have only one word, because 'grep ' is a quoted unit, which is concatenated with SomeString and then again concatenated with ' $File'. The variable $File is not even replaced with its value because of the use of single quotes. The proper way to do that is grep 'SomeString' "$File".
Shortest (correct) version:
grep -q "something" file; [ $? -eq 0 ] && echo "yes" || echo "no"
can be also written as
grep -q "something" file; test $? -eq 0 && echo "yes" || echo "no"
but you dont need to explicitly test it in this case, so the same with:
grep -q "something" file && echo "yes" || echo "no"
##To check for a particular string in a file
cd PATH_TO_YOUR_DIRECTORY #Changing directory to your working directory
File=YOUR_FILENAME
if grep -q STRING_YOU_ARE_CHECKING_FOR "$File"; ##note the space after the string you are searching for
then
echo "Hooray!!It's available"
else
echo "Oops!!Not available"
fi
grep -q [PATTERN] [FILE] && echo $?
The exit status is 0 (true) if the pattern was found; otherwise blankstring.
if grep -q [string] [filename]
then
[whatever action]
fi
Example
if grep -q 'my cat is in a tree' /tmp/cat.txt
then
mkdir cat
fi
In case you want to checkif the string matches the whole line and if it is a fixed string, You can do it this way
grep -Fxq [String] [filePath]
example
searchString="Hello World"
file="./test.log"
if grep -Fxq "$searchString" $file
then
echo "String found in $file"
else
echo "String not found in $file"
fi
From the man file:
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by newlines, any of
which is to be matched.
(-F is specified by POSIX.)
-x, --line-regexp
Select only those matches that exactly match the whole line. (-x is specified by
POSIX.)
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit immediately with zero
status if any match is
found, even if an error was detected. Also see the -s or --no-messages
option. (-q is specified by
POSIX.)
Try this:
if [[ $(grep "SomeString" $File) ]] ; then
echo "Found"
else
echo "Not Found"
fi
I done this, seems to work fine
if grep $SearchTerm $FileToSearch; then
echo "$SearchTerm found OK"
else
echo "$SearchTerm not found"
fi
grep -q "something" file
[[ !? -eq 0 ]] && echo "yes" || echo "no"

Resources