1833875 Members
3155 Online
110063 Solutions
New Discussion

strings multiple files

 
SOLVED
Go to solution
Robert-Jan Goossens
Honored Contributor

strings multiple files

Hi all,

I would like to search for a string in multiple binary files, something simular to a search below in ascii files.

# find /dir | xargs grep "string"
file:result
file:result

is this possible with the strings command ?

Thanks,
Robert-Jan
17 REPLIES 17
Steven E. Protter
Exalted Contributor

Re: strings multiple files

With a loop

results=/tmp/resultset.txt
while read -r fname
do
strings $fname >> $results
done < filelist

Steven E Protter
Owner of ISN Corporation
http://isnamerica.com
http://hpuxconsulting.com
Sponsor: http://hpux.ws
Twitter: http://twitter.com/hpuxlinux
Founder http://newdatacloud.com
Pete Randall
Outstanding Contributor

Re: strings multiple files

R-J,

$ find /home |strings |grep rcp
/home/plr/rcpsysfiles
/home/plr/rcpsysfiles.bak
$

It works but doesn't give the result, just the file. Is this what you're looking for?


Pete

Pete
Peter Godron
Honored Contributor

Re: strings multiple files

Robert-Jan,
Could Steves's idea be improved to ?:

results=/tmp/resultset.txt
while read -r fname
do
# Show the filename
echo $fname >> $results
# Added the grep for the string looked for
strings $fname | grep "string" >> $results
done < filelist

Regards
H.Merijn Brand (procura
Honored Contributor

Re: strings multiple files

GNU grep

# for i in `grep -l -a -r string /dir` ; do
# echo $i
# strings $i | grep string
# done

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Robert-Jan Goossens
Honored Contributor

Re: strings multiple files

Hi Pete,

# find . | strings | grep '@(#)CC'
is searching for filenames not inside the files.

I need to find the files which have the line starting with the string "@(#)CC"

Robert-Jan

Steven + Peter puzzle not solved yet :-)

Merijn, not possible to install gnu grep.
Peter Godron
Honored Contributor
Solution

Re: strings multiple files

Robert-Jan,
how about:
#!/usr/bin/sh
find /dir > /tmp/filelist
results=/tmp/resultset.txt
while read -r fname
do
# Show the filename
echo $fname >> $results
# Added the grep for the string looked for
strings $fname | grep "^"@(#)CC" >> $results
done < /tmp/filelist

Regards
H.Merijn Brand (procura
Honored Contributor

Re: strings multiple files

http://www.ust.hk/itsc/unix/sw/grep-2.4.2.html

Slowaris 9 and up seem to have ggrep by default. I cannot check

Slow but it works:

# find /dir -type f -exec strings {} \; | grep '^@(#)CC'

BUT! that pattern is a 'what' ident. Do you have 'what' program?

If you don't here's a version in perl:

--8<--- pwhat
#!/pro/bin/perl -w

$/ = "@(#)";

$pat = -f $ARGV[-1] ? "^" : pop @ARGV;

<>;
while (<>) {
my $i = index ($_, "\0");
$i == -1 and next;
my $w = substr $_, 0, $i;
$w =~ m/---/ or $w =~ m/$pat/ or next;
print "\t$w\n";
}
-->8---

Easy to extend with File::Find to search recursive

Enjoy, Have FUN! H.Merijn

Enjoy, Have FUN! H.Merijn
Stephen Keane
Honored Contributor

Re: strings multiple files

Create a short script (say fred.sh)

#!/bin/sh

CT=`strings "$1" | grep "^$2" | wc -l`
if [ "$CT" -ne 0 ]
then
echo $1
fi

Then run find command

find /dir -type f -exec ./fred.sh {} "string" \;
Pete Randall
Outstanding Contributor

Re: strings multiple files

R-J,

Sorry about the first attempt. This appears to work, but can be extremely slow unless you severely limit its' scope:

find /home/plr/tmp -exec strings {} \; |grep pckey
rcp /root/pckey $1:/tmp/pckey
echo " copying /tmp/pckey "


Pete


Pete
john korterman
Honored Contributor

Re: strings multiple files

Hi,
a bit primitive, but may be better than nothing.

#!/usr/bin/sh
previous=""
find "$1" -type f -print| while read line
do
if [ "$line" != "$previous" ]
then
strings "$line" | grep -q "$2" 2>/dev/null
if [ "$?" = "0" ]
then
echo "$line:"
strings "$line"| grep "$2" 2>/dev/null
previous="$line"
fi
fi
done
~


Try running it with "$1" as your starting directory for the search and "$2" as the string to search for.

regards,
John K.
it would be nice if you always got a second chance
Robert-Jan Goossens
Honored Contributor

Re: strings multiple files

Stephen,

Tried it,

it came back with all the filenames
./HKPBB102
./HKPBB104
./DBSBB102
./DBSBB104
./DBSBB105
./DBSBB106
./ITBBB001

ls | while read LINE
do
strings $LINE | grep '^@(#)CC'
done

comes back with all the strings

@(#)CC AAPVG248 01-10-2001 BAPE SFR4467
@(#)CC AAPVG290 15-06-2001 WH
@(#)CC AAPVG290 26-06-2001 WH Technical Review Changes
@(#)CC AAPVG290 28-06-2001 SFR4082 WH
@(#)CC AAPVG290 30-07-2001 SFR4232 BAPE
@(#)CC AAPVG290 30-07-2001 SFR4234 BAPE
@(#)CC AAPVG290 31-07-2001 VTW1118

RJ
A. Clay Stephenson
Acclaimed Contributor

Re: strings multiple files

'I need to find the files which have the line starting with the string "@(#)CC"'

It's rather difficult to mix the concept of "line" with "binary". Which is it? It really can't be both. You have to understand how the strings command works. It scans through data until it detects a certain number of consectutive printable ASCII characters. That "certain number" varies with the implementation but it's generally 3 or more. When that condition is met, the consectutive printable characters are output.
When you see the output of strings broken into lines, it is really nothing of the sort.

You probably need to change your request to something like "\n@(#)CC" or "\r@(#)CC" or "\f@(#)CC" or "@(#)CC" iff it occurs at the beginning of the file. Note that these sequences (though with low probability) occur in purely binary data so that accidental "hits" are possible.

This is really a job for Perl because it is one of the few scripting languages that can handle text or binary data well.
If it ain't broke, I can fix that.
H.Merijn Brand (procura
Honored Contributor

Re: strings multiple files

OK, this one should work better:

--8<---
#!/usr/bin/perl

use strict;
use warnings;

use File::Find;

$/ = "@(#)";

my $dir = @ARGV && -d $ARGV[0] ? shift (@ARGV) : ".";

find (sub {
-f or return;
open my $f, "<$_";
<$f>;
while (<$f>) {
my $i = index ($_, "\0");
$i == -1 and next;
my $w = substr $_, 0, $i;
print "\t$w\n";
}
}, $dir);
-->8---

You can change the path to be

$/ = "@(#)CC";

And get that included int the output lines as

print "\t$/$w\n";

Enjoy, Have FUN! H.Merijn [ who actually tested this chunk of code this time ]
Enjoy, Have FUN! H.Merijn
Stephen Keane
Honored Contributor

Re: strings multiple files

It will list the filenames that contain the string. What is it you are trying to do exactly?
Robert-Jan Goossens
Honored Contributor

Re: strings multiple files

Stephen,

I'm having a chat with the developer, you could be completly right. ( do I need both strings and filename ? )

Robert-Jan
Biswajit Tripathy
Honored Contributor

Re: strings multiple files

If I understand the question correctly, this should
do:

--------
for f in $(find /dir)
do
for line in $(strings $f)
do
echo $line | grep -q "string"
if [ $? -eq 0 ]
then
echo $f:$line
fi
done
done
---------

- Biswajit
:-)
Robert-Jan Goossens
Honored Contributor

Re: strings multiple files

Not ideal but workable.

create a small script search.sh

#!/bin/ksh

CT=`strings "$1" | grep "^$2" | grep -v "| " | wc -l`
if [ "$CT" -ne 0 ]
then
echo $1
strings "$1" | grep "^$2" | grep -v "| "
fi

# find /directory -type f -exec ./search.sh {} "@(#)CC" \;

Thanks all for your input.

Robert-Jan