Find and replace using xargs sed - can I save the results to a file?

19,443

Looks like a useless use of xargs, as often in combination with find.

find . -type f -exec grep 'foo' -l {} ";" -exec sed -i 's|foo|bar|g' {} ";" -ls > file.lst

Use it with care, since I didn't test it. I'm not sure, whether you like to change the list of filenames, or the file content. Since you search with grep and sed, I think only working with sed should be sufficient:

find . -type f -exec sed -i 's|foo|bar|g' {} ";" -ls > file.lst
Share:
19,443
Lewis
Author by

Lewis

Updated on July 23, 2022

Comments

  • Lewis
    Lewis almost 2 years

    My code to replace all instances of 'foo' with 'bar' :

    find . -type f |
    xargs grep 'foo' -l |
    xargs sed -i 's|foo|bar|g'
    

    I'd like to save a list of the modified files to a text document. Is it possible?

    EDIT :

    This is the final code that worked for me :

    find . -type f -print0 |
    xargs -0 grep 'foo' -l |
    tee result.txt |
    xargs -0 sed -i 's|foo|bar|g'
    

    Not sure whether this is the quickest way, but for a few thousand files the difference in speed between this and other suggested methods is probably very small.

  • Lewis
    Lewis about 12 years
    I only wish to modify content, not filenames. The only files that should be modified are those that contain the string.
  • Lewis
    Lewis about 12 years
    I should add, there are many thousands of files being searched and modified. Is exec better than xargs for this?
  • user unknown
    user unknown about 12 years
    xargs is an additional process, and you can't do much with it, what can't be done with -exec more easily. Find knows what part of a result is a filename, where it starts and where it ends. To use xargs securely you have to sanitize against blanks, linebreaks and other ugliness in filenames (which is possible with -print0, but makes the command more large). (But I have to add 2 or 3 ";" in the exec argument. If your limiting factor is HDD-speed, which I suspect, than using parallel invocation is not of much use. But even parallel invocation is possible with + instead of ";".
  • user unknown
    user unknown about 12 years
    About many thousands files: If the first "foo" is close to the end of the file, it is read two times, once by grep, once by sed. If there is no "foo", it is entirely read by grep in your example, and entirely read by sed in mine. If the "foo" is close to the beginning, it is read a bit with grep by your, and entirely with sed. By my approach only entirely with sed. Why should sed be slower than grep?
  • Lewis
    Lewis about 12 years
    OK, I think you are correct. However, I think your second example will cause every file's modified date to change, regardless of whether it contains "foo".