Search code examples
bashshellgrep

Can't capture output of find + grep in Bash


I'm hitting my head against the wall here with this... I'm trying to create a simple script that loads a file as an array, and searches for each line through files whether there is a match.

  • If a match is found, do nothing
  • If no match is found, write the entry to a file

The script looks something like this:

#!/usr/bin/env bash

echo "Please enter the full path to the directory where the log files are located:"
read -r log_directory

readarray -t lines < mac-addresses.txt

echo "Loaded ${#lines[@]} mac addresses to search for."

for mac_address in "${lines[@]}"
do
  found=$(find "$log_directory" -name 'dhcpd.log.[1-30]' -exec grep "$mac_address" {} + | wc -l)

  echo "Result for $mac_address $count"
done

This is what happens when I call the script:

Please enter the full path to the directory where the log files are located:
./logs
Loaded 2 mac addresses to search for.
0
 esult for d4:3d:7e:ce:24:14
0
 esult for 00:12:34:56:78:9a
  1. Why is the output from the echo command mangled?
  2. How do I capture the output from find "$log_directory" -name 'dhcpd.log.[1-30]' -exec grep "$mac_address" {} + | wc -l ?

I've tried using $(), tried using backticks, but I can't really seem to capture the command correctly. Here's an output example:

$ find "./logs" -name 'dhcpd.log.[1-30]' -exec grep "d4:3d:7e:ce:24:14" {} + | wc -l
3

arned@Saturn MINGW64 /d/src/Scripts/mac-address-searcher
$ find "./logs" -name 'dhcpd.log.[1-30]' -exec grep "00:12:34:56:78:9a" {} + | wc -l
0

So the command is doing exactly what I want, but I just can't get it to work correctly inside my bash script...


Solution

  • Credit goes to @KamilCuk for pointing out the issue with Windows:

    # Remove special characters from Windows such as the carriage return.
    # Otherwise the search will fail as the input gets messed up.
    cleaned_entry=${mac_address//$'\r'}
    

    Since the input file comes from a Windows system, the carriage return needs to be removed for each entry. This makes the commands work correctly.