Find and replace for all files in directory

Hello,

I want to find all instances of "ABC123" (case sensitive) in ALL files in the directory /home/usr/stuff/ file.txt and replace all the instances with "LMNOP789"

The ownership and permissions must be preserved.

How can this be done from a command line?
I am using Red Hat 7.

Thanks!
LVL 16
hankknightAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
SunjithConnect With a Mentor Commented:
> (find /home/usr/stuff/ -type f | xarg vi -e -c "%s/ABC123/LMNOP789/g" -c "wq" ) 2>/dev/null

That's good. Just a correction. It should be "xargs" instead of "xarg"

Grepping is a better idea than find because it filters out the files needed to be processed by vi and grep processes file much faster than vi. Combining all the ideas, the better command would be:
--------
grep -srl "ABC123" /home/usr/stuff/ | xargs vi -e -c "%s/ABC123/LMNOP789/g" -c "wq"
--------

Though there wouldn't be too many errors as you got with the previous script, if you are very particular, you may redirect the std error as well:
--------
grep -srl "ABC123" /home/usr/stuff/ | xargs vi -e -c "%s/ABC123/LMNOP789/g" -c "wq" 2>/dev/null
--------
0
 
blklineCommented:
cd /home/usr/stuff; for f in $(ls *.txt); do cat $f | sed -e 's/ABC123/LMNOP789/g' > tmp$$.txt && chown --reference=$f tmp$$.txt; chmod --reference=$f tmp$$.txt; mv -f tmp$$.txt $f; done

Keep in mind that if the owner of the file is someone other than yourself and you're not running as root then you may not be able to overwrite the file.

Written to be more legible it looks like this:

cd /home/usr/stuff
for f in $(ls *.txt)
do
    cat $f | sed -e 's/ABC123/LMNOP789/g' > tmp$$.txt \
    && chown --reference=$f tmp$$.txt; \
    chmod --reference=$f tmp$$.txt; \
    mv -f tmp$$.txt $f
done
0
 
SunjithCommented:
>I want to find all instances of "ABC123" (case sensitive) in ALL files in the directory /home/usr/stuff/  and
>replace all the instances with "LMNOP789"
>
>The ownership and permissions must be preserved.

Here's the script (one method) for that:
--------
for i in `find /home/usr/stuff/ -type f`; do vi -e -c "%s/ABC123/LMNOP789/g" -c "wq" $i; done
--------
Copy the command exactly. If you are typing, make sure all quotations are correct (Note that the first two single quotes is the key usually above your 'tab' key).
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
blklineCommented:
I never gave a thought to using vi in this manner.   Thanks!

Oh, make it:

find /home/usr/stuff/ -type f -name "*.txt"   as I think from the specs that the filenames all have a txt extension.
0
 
SunjithCommented:
You are welcome. BTW, FYI, the filenames need not necessarily have a txt extension.
0
 
hankknightAuthor Commented:
Thanks!  It worked, but it returned several pages of errors:

                   Error detected while processing command line:
                   Pattern not found: storefront

For future refference, is there a way to supress the errors?

Thanks!
0
 
brettmjohnsonCommented:
You get the errors because some of the "ALL files in the directory" don't
contain the source pattern for the replace.  Rather than 'find', why don't
you use 'grep -l' to limit the files to those that contain the source pattern.

for i in `grep -l "ABC123" /home/usr/stuff/*.txt`; do vi -e -c "%s/ABC123/LMNOP789/g" -c "wq" $i; done

0
 
LuxanaConnect With a Mentor Commented:
> For future refference, is there a way to supress the errors?

you can redirect standart error to /dev/null

lets take blkline's example :

find /home/usr/stuff/ -type f -name "*.txt" 2> /dev/null

so all errors will be send to /dev/null and you get just STDOUT
0
 
yuzhConnect With a Mentor Commented:
How about:

(find /home/usr/stuff/ -type f | xarg vi -e -c "%s/ABC123/LMNOP789/g" -c "wq" ) 2>/dev/null

please credit to  Sunjith's vi statement, you can also use perl/sed to do the same job.
0
 
yuzhCommented:
Sorry about the typo, it should be "xargs", Sunjith thanks for the correction.
0
 
EinarThCommented:
I'd use grep a bit differently:

for f in $(find /usr/home/stuff -type f) ; do grep ABC123 $f && cat $f | sed "s/ABC123/LMNOP789/g" > tmp$$.txt && chown --reference=$f tmp$$.txt; mv -f tmp$$.txt $f; done

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.