Linux Bash script grep error - linux

So my professor and I worked on this for about 2 hours and couldn't figure out what the problem was so I am hoping someone can see what we missed.
askDelete()
{
echo -e " Still want to delete it? (y/n)\n"
read answer
if [ "$answer" = 'y']; then
rm $1
else
echo -e "\nFile was not removed\n"
fi
}
#############################################
clear
#script starts here
echo -e "\n\tCleaner Script\n"
dir=`pwd`
while [ "$choice" -ne 3 ] || [ "$choice" != "quit" ]
do
echo -e "\nEnter 1 to delete by filename or type the word file."
echo -e "\nEnter 2 to delete by a string within a file or type the word string"
echo -e "\nEnter 3 or quit to exit this program.\n"
read choice
case "$choice" in
1|"file") echo -e"Enter the name of the file to delete: "
read file
result=$(find . -name "$file")
if [ -z $result ]; then
echo "File not found"
else
askDelete $file
fi
;;
2|"string") echo -e "Enter the sting to delete the files that contain it: "
read searchstring
result=$(find $dir -type f -perm /400)
echo $result
for file in $result;
do
echo -e "String is $searchstring \nFile is $file"
grep –q "$searchstring" "$file"
if [ $? -eq 0 ]; then
echo "****MATCH****"
askDelete $file
fi
done
;;
3|"quit") echo -e "Exiting program"
break;;
*) echo -e "\nChoice not listed";;
esac
done
and when I do selection 2 I get to the grep and get this error message with my troubleshooting messages.
Enter the sting to delete the files that contain it:
pizza
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/smith.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data2.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones2.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/cleaner.sh
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data.txt
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/smith.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data2.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones2.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/cleaner.sh
grep: pizza: No such file or directory
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/cleaner.sh:
grep –q "$searchstring" "$file"
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data.txt
grep: pizza: No such file or directory
Grep also works just fine outside the BASH script with the absolute paths. Tested the if statement and if I take out the -eq it does work properly because it reads that grep did successfully run just that the directory was not found. From what I can tell it is ignoring my file and instead is using the string search as the directory.

The dash part of the '-q' argument to grep is a special non-ascii character, probably an en-dash in UTF-8, I didn't look too hard. Grep doesn't interpret the en-dash as starting an option and does a search for the string '–q' in the file list. 'pizza' is in the file list.
This can happen easily if you copy code from a web page or a word doc. Anyway, delete the -q and retype it and you script should work better.

Related

Checking if a multi-line string exist in a file

I wanted to make a bash script to check if each line of multi-line string already exist in a file.
I had already wrote some code, but I'm not sure if it will work:
str="
this is
a multiple
line
string"
while read -r f; do
while read -r s: do
if [ $r == $s ]; then break; fi
done
done << some_file.txt
any ideas to get it working ?
Here's a trick if you can load the whole file twice to memory:
str="
this is
a multiple
line
string"
# Read the whole file in variable
content=$(<some_file.txt)
# Replace str to nothing in content
repr=${content/${str}}
# Check if it's the same.
if [[ "$content" != "$repr" ]]; then
# If it's not, means content contains str and it was removed.
echo "Contains"
fi
It can be a perl one-liner:
if perl -0777 -sne '/$text/ or exit 1' -- -text="$str" "$file"
then
echo Found
else
echo not found
fi
The -0777 option slurps the whole file into memory
This could be a solution in bash:
Reading the string lines into an array.
Then, for each string line in the array:
Checking the file contains a whole line equal to that string line.
Stop walking the array once a check fails.
#!/bin/bash
file="$1"
names="
this is
a multiple
line
string"
# Read string lines into an array
readarray -t <<< $names
# Walk array of lines
all_strings_found=true
for string in "${MAPFILE[#]}"; do
if ! grep -q "^$string$" $file; then
echo "'"$string"'" "not found"
all_strings_found=false
break
fi
done
if [ "$all_strings_found" == true ]; then
echo "---> All strings found"
else
echo "---> NOT all strings found"
fi
I like case statements for this.
$ cat script
str1="
this is
a multiple
line
string"
str2="$1"
f="$(<$0)"
case "$f" in
*"$str1"*) echo "String 1 exists" ;;
*) echo "String 1 not found" ;;
esac
case "$f" in
*"$str2"*) echo "String 2 exists" ;;
*) echo "String 2 not found" ;;
esac
$ ./script esac
String 1 exists
String 2 exists
$ ./script foo
String 1 exists
String 2 not found

grep filename only in linux bash

I want to find a file. If user input "file.txt", then I need to echo the "file.txt". But if file name not found, just echo "not found". The code i have is for finding a word in a file. But how if I just need to search the file. If I write : result=`grep $filename`, it won't work. What's the format for grep filename?
#!/bin/bash
echo -n "File name : "
read filename
echo -n "Word : "
read word
result=`grep $word $filename`
if [ "$result" != "" ]
then
echo "$result"
else
echo "Not found"
fi
It looks like you are trying to determine if $word is present in $filename. If so:
if ! grep "$word" "$filename"; then
echo not found >&2
fi
The check to determine if the file exists seems redundant, since grep will emit an error message if the file does not exist, but perhaps you want something like:
if test -e "$filename" && ! grep "$word" "$filename"; then
echo "$word" is not found in "$filename" >&2
else
echo "$filename" does not exist >&2
fi
which will not print the redundant "not found" in addition to the error message from grep saying that the file does not exist.
With grep, you can try this way :
#!/bin/bash
OLDIFS="$IFS"
IFS=''
read -p "File name : " filename
IFS=$OLDIFS
grep -l '' "$filename" 2>/dev/null
! [ $? -eq 0 ] && echo "file $filename not found"
bemol : grep do not find a file with a size of 0.
If I read it right...
grep -l "$word" "$filename" 2>&- || echo "not found"
If $word exists in $filename the -l option will output the name of the file.
If not, grep will return an error exit code and the || ("or") will execute the echo.
$: echo foo > bar
$: grep -l foo ???
bar
$: rm bar
$: grep -l foo ??? 2>&- || echo "not found"
not found
The 2>&- closes STDERR so that grep doesn't throw an error message of its own.
Without it -
$: grep -l foo ??? || echo "not found"
grep: ???: No such file or directory
not found
Of course https://mywiki.wooledge.org/BashPitfalls#myprogram_2.3E.26- advises against closing standard streams, so you should probably use 2>/dev/null.
So, the whole script:
#!/bin/bash
read -p "Filename: " filename
read -p "Word: " word
grep -l "$word" "$filename" 2>/dev/null || echo "not found"

Bash: Counting instances of a string in text file with a loop

I am trying to write a simple bash script in which it takes in a text file, loops through the file and tells me how many times a certain string appears in the file. I want to eventually use this for a custom log searcher (for instance, search for the words 'log in' in a particular log file, etc.), but am having some difficulty as I am relatively new to bash. I want to be able to quickly search different logs for different terms at my will and see how many times they occur. Everything works perfectly until I get down to my loops. I think that I am using grep wrong, but am unsure if that is the issue. My loop codes may seem a little strange because I have been at it for a while and have been constantly tweaking things. I have done a bunch of searching but I feel like I am the only one who has ever had this issue (hopefully not because it is incredibly simple and I just suck). Any and all help is greatly appreciated, thanks in advance everyone.
edit: I would like to account for every instance of the string and not just
one instance per line
#!/bin/bash
echo "This bash script counts the instances of a user-defined string in a file."
echo "Enter a file to search:"
read fileName
echo " "
echo $path
if [ -f "$fileName" ] || [ -d "$fileName" ]; then
echo "File Checker Complete: '$fileName' is a file."
echo " "
echo "Enter a string that you would like to count the occurances of in '$fileName'."
read stringChoice
echo " "
echo "You are looking for '$stringChoice'. Counting...."
#TRYING WITH A WHILE LOOP
count=0
cat $fileName | while read line
do
if echo $line | grep $stringChoice; then
count=$[ count + 1 ]
done
echo "Finished processing file"
#TRYING WITH A FOR LOOP
# count=0
# for i in $(cat $fileName); do
# echo $i
# if grep "$stringChoice"; then
# count=$[ $count + 1 ]
# echo $count
# fi
# done
if [ $count == 1 ] ; then
echo " "
echo "The string '$stringChoice' occurs $count time in '$fileName'."
elif [ $count > 1 ]; then
echo " "
echo "The string '$stringChoice' occurs $count times in '$fileName'."
fi
elif [ ! -f "$fileName" ]; then
echo "File does not exist, please enter the correct file name."
fi
To find and count all occurrences of a string, you could use grep -o which matches only the word instead of the entire line and pipe the result to wc
read string; grep -o "$string" yourfile.txt | wc -l
You made basic syntax error in the code. Also, the variable of count was never updating as the the while loop was being executed in a subshell and thus the updated count value was never reflecting back.
Please change your code to the following one to get desired result.
#!/bin/bash
echo "This bash script counts the instances of a user-defined string in a file."
echo "Enter a file to search:"
read fileName
echo " "
echo $path
if [ -f "$fileName" ] ; then
echo "File Checker Complete: '$fileName' is a file."
echo " "
echo "Enter a string that you would like to count the occurances of in '$fileName'."
read stringChoice
echo " "
echo "You are looking for '$stringChoice'. Counting...."
#TRYING WITH A WHILE LOOP
count=0
while read line
do
if echo $line | grep $stringChoice; then
count=`expr $count + 1`
fi
done < "$fileName"
echo "Finished processing file"
echo "The string '$stringChoice' occurs $count time in '$fileName'."
elif [ ! -f "$fileName" ]; then
echo "File does not exist, please enter the correct file name."
fi

Finding max lines in a file while printing file name and lines separately?

So I keep messing this up and I think where I was going wrong was that the code i'm writing needs to return only the file name and number of lines from an argument.
So using wc I need to get something to accept either 0 or 1 arguments and print out something like "The file findlines.sh has 4 lines" or if they give a ./findlines.sh Desktop/testfile they'll get the "the file testfile has 5 lines"
I have a few attempts and all of them have failed. I can't seem to figure out how to approach it at all.
Should I echo "The file" and then toss the argument name in and then add another echo for "has the number of lines [lines]"?
Sample input would be from terminal something like
>findlines.sh
Output:the file findlines.sh has 18 lines
Or maybe
>findlines.sh /home/directory/user/grocerylist
Output of 'the file grocerylist has 16 lines
#! /bin/sh -
file=${1-findfiles.sh}
lines=$(wc -l < "$file") &&
printf 'The file "%s" has %d lines\n' "$file" "$lines"
This should work:
#!/bin/bash
file="findfiles.sh"
if [ $# -ge 1 ]
then
file=$1
fi
if [ -f $file ]
then
lines=`wc -l "$file" | awk '{print $1}'`
echo "The file $file has $lines lines"
else
echo "File not found"
fi
See sch's answer for a shorter example that doesn't use awk.

linux shell script: getting filename from a user input string

I would like to write a shell script in which I'll take a line input from user,which will contain some xxx.cpp as filename.
I want to get that "xxx" in another variable.
e.g.
if user give input as:
some params path/to/file/xyz.cpp more p/ara/ms
I want to get xyz which occurs before".cpp" and after last occurance of "/" before ".cpp"
Use basename [param] [.ext].
echo `basename $1 .cpp`
where 1 is the index of path/to/file.xyz in the argument list.
Here's a sample bash script to prompt the user for a list of files and filter all the input and display only the base name of files that end in '.cpp' (with .cpp removed) and which are readable
#!/bin/bash
echo Enter list of files:
read list_of_files
for file in $(echo $list_of_files); do
if echo $file | grep '\.cpp$' > /dev/null; then
if [[ -r $file ]]; then
fn=$(basename ${file})
fn=${fn%.*}
echo $fn
fi
fi
done

Resources