Searching Files for Text Strings
In the past, I’ve posted a couple of versions of this script in Bash and Korn shell. Here’s a much-expanded and improved Bash version. The script will take your input and look for files containing the specified text string. You have an option of specifying file type, directory depth, modification time and other parameters to narrow down your search. This script will prove useful for making system and application configuration changes.
#!/bin/bash
# 2014 KrazyWorks.com
this_script=$0
configure() {
this_time=$(date +'%Y-%m-%d_%H%M%S')
this_time_db=$(date +'%Y-%m-%d %H:%M:%S')
this_host=$(hostname | awk -F'.' '{print $1}')
this_hostid=$(hostid)
maxsize_mb=10
tail_lines=5
random=$(echo "`expr ${RANDOM}${RANDOM} % 100000`+1"|bc -l)
od="/tmp"
ofn="search_string_${random}_${this_time}_${this_host}_${this_hostid}_tmp.txt"
of="${od}/${ofn}"
if [ -f "${of}" ] ; then /bin/rm -f "${of}" ; fi
touch "${of}" ; chmod 600 "${of}"
whiptailstatus=$(which whiptail > /dev/null 2>&1 ; echo $?)
}
get_search_string() {
if [ ${whiptailstatus} -eq 0 ]
then
search_string=$(whiptail --inputbox "Enter search string:" 8 78 --title "Search Dialog" 3>&1 1>&2 2>&3)
else
echo -n "Enter search string: "
read search_string
fi
if [ -z "${search_string}" ]
then
echo "Search string cannot be null"
exit 1
fi
}
get_search_dir() {
if [ ${whiptailstatus} -eq 0 ]
then
search_dir=$(whiptail --inputbox "Enter search directory:" 8 78 `pwd` --title "Search Dialog" 3>&1 1>&2 2>&3)
else
echo -n "Enter directory to search [`pwd`]: "
read search_dir
fi
if [ -z "${search_dir}" ]
then
search_dir=$(pwd)
else
if [ ! -d "${search_dir}" ]
then
echo "Directory not found: ${search_dir}"
exit 1
fi
fi
}
get_dir_depth() {
if [ ${whiptailstatus} -eq 0 ]
then
dir_depth=$(whiptail --inputbox "Directory depth limit:" 8 78 --title "Search Dialog" 3>&1 1>&2 2>&3)
else
echo -n "Directory depth limit [unlimited]: "
read dir_depth
fi
if [ -z "${dir_depth}" ]
then
dir_depth=64000
fi
}
get_file_name() {
if [ ${whiptailstatus} -eq 0 ]
then
file_name=$(whiptail --inputbox "Enter partial filename:" 8 78 * --title "Search Dialog" 3>&1 1>&2 2>&3)
else
echo -n "Enter partial filename [*]: "
read file_name
fi
if [ -z "${file_name}" ]
then
file_name="*"
fi
}
get_file_age() {
if [ ${whiptailstatus} -eq 0 ]
then
mod_time=$(whiptail --inputbox "Enter maximum file age:" 8 78 --title "Search Dialog" 3>&1 1>&2 2>&3)
else
echo -n "Enter maximum file age [unlimited]: "
read mod_time
fi
if [ -z ${mod_time} ]
then
mod_time=14600
elif ! [[ "${mod_time}" =~ ^[0-9]+$ ]]
then
echo "File age must be an integer"
exit 1
fi
}
get_file_type() {
if [ ${whiptailstatus} -eq 0 ]
then
file_type_search=$(whiptail --menu "Specify types of files to search:" --title "Search Dialog" 20 78 16 "1" "Only search ASCII files" "2" "Search all files" 3>&1 1>&2 2>&3)
else
echo -n "Specify types of files to search [text/all]: "
read file_type
fi
}
run_search_ascii() {
i=1 ; j=0 ; k=0
find "${search_dir}" -maxdepth ${dir_depth} -type f -iname "*${file_name}*" -mtime -${mod_time} -print | while read line
do
if [ `file "${line}" | egrep -ic "POSIX|ASCII"` -eq 1 ] && [ -r "${line}" ]
then
clear
echo "Found: ${j}"
echo "-----------------------------------"
if [ -r "${of}" ]
then
if [ ${j} -gt ${tail_lines} ] ; then echo "..." ; fi
tail -${tail_lines} "${of}" | while read line3
do
(( k = k + 1 ))
echo -e "${k}:t${line3}"
done
fi
echo "Searching (${i}): ${line}"
(( i = i + 1 ))
if [ `egrep -ic "${search_string}" "${line}"` -gt 0 ]
then
echo "${line}" >> "${of}"
(( j = j + 1 ))
fi
fi
done
}
run_search_all() {
i=1 ; j=0 ; k=0
find "${search_dir}" -maxdepth ${dir_depth} -type f -iname "*${file_name}*" -mtime -${mod_time} -size -${maxsize_mb}M -print | while read line
do
if [ -r "${line}" ]
then
clear
echo "Found: ${j}"
echo "-----------------------------------"
if [ -r "${of}" ]
then
if [ ${j} -gt ${tail_lines} ] ; then echo "..." ; fi
tail -${tail_lines} "${of}" | while read line3
do
(( k = k + 1 ))
echo -e "${k}:t${line3}"
done
fi
echo "Searching (${i}): ${line}"
(( i = i + 1 ))
if [ `strings "${line}" | egrep -ic "${search_string}"` -gt 0 ]
then
echo "${line}" >> "${of}"
(( j = j + 1 ))
fi
fi
done
}
show_results() {
clear
echo "Found `wc -l ${of} | awk '{print $1}'`"
if [ -r "${of}" ]
then
echo "Results are in ${of}"
echo "--------------------------------------"
echo ""
cat "${of}" | while read line2
do
echo -ne "${line2}t" ; echo -ne "Modified: " ; stat -c "%y" "${line2}" | awk -F '.' '{print $1}'
egrep -i "${search_string}" "${line2}" | tail -${tail_lines} | sed -e "s/^[ t]*/t/" | while read line4
do
echo -e "t${line4}" | fold -w `tput cols` | head -1
done
if [ `egrep -ic "${search_string}" "${line2}"` -gt ${tail_lines} ]
then
echo "..."
fi
echo ""
done
echo ""
fi
}
# RUNTIME
configure
get_search_string
get_search_dir
get_dir_depth
get_file_name
get_file_type
get_file_age
if [ ${file_type_search} -eq 1 ]
then
run_search_ascii
elif [ ${file_type_search} -eq 2 ]
then
run_search_all
else
exit 1
fi
show_results | more

