简体   繁体   中英

Invoke sed only on files which contain a certain string - problems with whitespaces in filenames

Using bash, I try to make a substitutions in files (replace B with C ), but only in files which contain a certain string A .

I tried

grep -Rl "A" | xargs sed -i 's/B/C'

But this fails when the filenames contain whitespaces

As an ugly workaround, I came up with the following solution which replaces the whitespaces with a placeholder :

for  FILE in `grep -Rl "A"   | tr " " "@"`; 
  do F1=`echo  $FILE | tr "@" " "`;sed 's/B/C/' "$F1"; 
done

is there a more elegant solution?

You can use --null for grep and -0 for xargs :

grep --null -Rl 'A' . | xargs -0 sed -i '' 's/B/C/'

--null Outputs a zero byte (the ASCII NUL character) after each filename of grep command and xargs -0 reads null terminated input to xargs .

You could combine the usage of argument --null for grep, with the argument of -0 for xargs, to have the arguments be separated by NUL characters instead.

man grep:
--null  Prints a zero-byte after the file name.

man xargs:
-0      Change xargs to expect NUL (``\0'') characters as separators,
        instead of spaces and newlines. This is expected to be used in 
        concert with the -print0 function in find(1).

The UNIX tool to find files is named, appropriately enough, find not grep .

find . -type f -exec grep -l -Z 'A' {} + |
xargs -0 sed -i 's/B/C'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM