Networking

Unix and Linux network configuration. Multiple network interfaces. Bridged NICs. High-availability network configurations.

Applications

Reviews of latest Unix and Linux software. Helpful tips for application support admins. Automating application support.

Data

Disk partitioning, filesystems, directories, and files. Volume management, logical volumes, HA filesystems. Backups and disaster recovery.

Monitoring

Distributed server monitoring. Server performance and capacity planning. Monitoring applications, network status and user activity.

Commands & Shells

Cool Unix shell commands and options. Command-line tools and application. Things every Unix sysadmin needs to know.

Home » Commands & Shells, Featured

Searching Files for Text Strings

Submitted by on July 28, 2014 – 4:22 pm

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

 

Print Friendly, PDF & Email

Leave a Reply