Linux shell script to search logs with user input - linux

I am trying to write a script which searches a tomcat log from a keyword which the user inputs. I'm having issues getting the read command to work correctly.
#!/bin/bash
TOM1=/ap/mvr/servers/tomcat1/logs/
TOM2=/ap/mvr/servers/tomcat2/logs/
find $TOM1 $TOM2 -type f -name "mvr-gateway.log" | while read file
echo "What do you want to search for? " keyword
read keyword
do
LOGERRORS=$(grep -B1 -A1 $keyword $file)
if [[ ! -z $LOGERRORS ]]
then
echo $file
else echo No Data Found
fi
done

try this:
#!/bin/bash
TOM1=/ap/mvr/servers/tomcat1/logs/
TOM2=/ap/mvr/servers/tomcat2/logs/
read -p "What do you want to search for?" search_term
grep -B1 -A1 ${search_term} $(find $TOM1 $TOM2 -type f -name "mvr-gateway.log")
As mentioned before, ask first the term you are searching for.

Related

Bash - alternative for: ls | grep

I use the following pipe as variable in a script:
match=$( ls | grep -i "$search")
this is then used in an if statement:
if [ "$match" ]; then
echo "matches found"
else
echo "no matches found"
fi
what would be an alternative if I did not want to use find?
ShellCheck recommends:
ls /directory/target_file_pattern
but I do not get the syntax right to get the same result.
also I want no output when there are no matches for the if statement to work.
If you just want to tell if there exist any matches with bash you could use the builtin compgen like so:
if compgen -G 'glob_pattern_like_your_grep' >/dev/null; then
echo "matches found"
else
echo "no matches found"
fi
if you want to operate on the files that are matched, find is usually the right tool for the job:
find . -name 'glob_pattern_like_your_grep' -exec 'your command to operate on each file that matches'
the key though is that you have to use glob patterns, not regex type patterns.
If your find supports it, you might be able to match a regex like
find . -regex 'pattern'
and use that in either the if or with -exec
Use find:
match="$(find . -path "*${search}*" -printf "." | wc -c)"
$match will contain the number of matches. You can check it like this:
if [ "${match}" -gt 0 ] ; then
echo "${match} files found"
else
echo "No files found"
fi

Renaming directories at multiple levels using find from bash

I'm looping over the results of find, and I'm changing every one of those folders, so my problem is that when I encounter:
/aaaa/logs/ and after that: /aaaa/logs/bbb/logs, when I try to mv /aaaa/logs/bbb/logs /aaaa/log/bbb/log it can't find the folder because it has already been renamed. That is, the output from find may report that the name is /aaaa/logs/bbb/logs, when the script previously moved output to /aaaa/log/bbb/.
Simple code:
#!/bin/bash
script_log="/myPath"
echo "Info" > $script_log
search_names_folders=`find /home/ -type d -name "logs*"`
while read -r line; do
mv $line ${line//logs/log} >>$script_log 2>&1
done <<< "$search_names_folders"
My Solution is:
#!/bin/bash
script_log="/myPath"
echo "Info" > $script_log
search_names_folders=`find /home/ -type d -name "logs*"`
while read -r line; do
number_of_occurrences=$(grep -o "logs" <<< "$line" | wc -l)
if [ "$number_of_occurrences" != "1" ]; then
real_path=${line//logs/log} ## get the full path, the suffix will be incorrect
real_path=${real_path%/*} ## get the prefix until the last /
suffix=${line##*/} ## get the real suffix
line=$real_path/$suffix ## add the full correct path to line
mv $line ${line//logs/log} >>$script_log 2>&1
fi
done <<< "$search_names_folders"
But its bad idea, Has anyone have other solutions?
Thanks!
Use the -depth option to find. This makes it process directory contents before it processes the directory itself.

How do I search for a file based on what is output by a command running on that file

I am working on a project for one of my professors and he asked me to sort a couple hundred .fits images based on their header files (specifically what star they are images of) I think that grep would be the best way to do this however I can't seam to figure out how to use grep based on the header.
I am entering:
ls | imhead *.fits | grep -E -r "PG\ 1104+243" *
to just list them out for now, once they are listed I know how to copy them into a directory.
I am new to using grep so I am unsure as to where my error lies? any help would be greatly appreciated! Thanks!
Assuming that imghead will extract the headers of the .fits as txt, you can use a simple shell script to do it:
script.sh
#!/bin/bash
grep "$1" "$2" > /dev/null 2>&1 && echo "$2"
Note that the + is a special character if you use extended regular expression, meaning if you pass the -E as in the question. A simple grep without any options should do the trick here.
Use find to exec the script on every *.fits file in the current folder:
find -maxdepth 1 -name '*.fits' -exec ./script.sh 'PG 1104+243' {} \;
If you are going to copy/move/alter or do something with the files you find, you might be better off, in terms of complexity and ease of quoting, using a loop like this:
#!/bin/bash
find . -name \*.fits -print0 | while read -d '' -r file; do
echo Checking file: $file
imhead "$file" | grep -q 'PG 1104+243'
if [ $? -eq 0 ]; then
echo Object matches: $file
fi
done

Bash script - how to keep looping 'find' command until file/s are found?

I am very new to linux scripting & am trying to set up a simple loop which will:
Ask user for file name
Search a specific directory for the file
If no files are found, ask the user to reinput a file name
If files are found, move on to the next step of the script
This is what I have so far, but it is not looping at all(i.e when no files are found, it is not asking the user to re-enter a file name. )
#!/bin/bash
read -p "Enter file name: " file
find /directory/ -name "$file" -print
while [ "$?" -ne 0 ]; do
read -p "File not found. Please re-enter file name: " file
find /directory/ -name "$file" -print
done
echo "rest of script etc"
Any help is appreciated! :)
The easiest way to do this is probably using globstar (available with bash 4)
#!/bin/bash
shopt -s globstar
while true; do
read -p "Enter file name: " file
for f in /directory/**/"$file"; do
echo "$f"
break 2 # escape both loops
done
echo "'$file' not found, please try again."
done
echo "rest of script etc"
It's also possible to do with find, but slightly annoying, given that you can't use standard UNIX exit statuses:
#!/bin/bash
read -p "Enter file name: " file
found=$(find /directory/ -name "$file" -print -quit)
while [[ -z $found ]]; do
read -p "File not found. Please re-enter file name: " file
found=$(find /directory/ -name "$file" -print -quit)
done
echo "$found"
echo "rest of script etc"
Normally I wouldn't recommend parsing the output of find, but in this case we're only concerned as to whether or not there is any output.
The easiest and most portable way might be this:
# Loop until user inputted a valid file name
while true ; do
# Read input (the POSIX compatible way)
echo -n "Enter file name: "
read file
# Use find to check if the file exists
[ $(find /etc -type f -name "$file" 2>/dev/null | wc -l ) != "0" ] && break
# go to next loop if the file does not exist
done
echo "Ok, go on here"

how to find and delete below line using shell script

Below line has printed in my all php project pages because of malicious attacks.Now think is how i can find and delete this lines using shell script
function_exists('date_default_timezone') ?
date_default_timezone_set('America/Los_Angeles') :
($_REQUEST['c_id']));
I tried with below script but i getting error.I mean to say I not able to match above line with sed commend.Please help me to correct this script..
#!/bin/sh
search='^function_exists\(\'date_default_timezone\'\)\ \?\ date_default_timezone_set\(\'America/Los_Angeles\'\)\ \:\ \(\$_REQUEST\[\'c_id\'\]\)\)\;'
for file in `find /root/test1 -name "*.php"`; do grep "$search" $file &> /dev/null if [ $? -ne 0 ]; then echo "Search string not found in $file!" else sed -i '/$search/d' $file
Try sed with : seperators rather than / since in your pattern America/La conflicts with / ir add a backslash so its America/la
You're not escaping the regex correctly. Try the following:
while IFS= read -r -d '' file; do
if grep -qF "function_exists('date_default_timezone') ? date_default_timezone_set('America/Los_Angeles') : (\$_REQUEST['c_id']));" "$file"
then
sed -i "s|function_exists('date_default_timezone') ? date_default_timezone_set('America/Los_Angeles') : (\$_REQUEST\['c_id'\]));|FOO|g" "$file"
fi
done < <(find /root/test1 -type f -name "*.php" -print0)
This might work for you (GNU sed)
pattern1='function_exists('\''date_default_timezone'\'''
pattern2='.*date_default_timezone_set('\''America\/Los_Angeles'\'') :'
pattern3='.*($_REQUEST\['\''c_id'\''\]));'
sed '/^'"$pattern1"'/{N;N;/^'"$pattern1$pattern2$pattern3"'/d}' file

Resources