find /tmp/ -type f                                      \
    \( -name "*.h" \) -o \( -name "*.cpp" \) -o         \
    \( \! -name "*.bak" \) -exec                        \
    sed -i '1s/^/#include <stdint.h>\n/' {} +

I am not completely sure that this is the right way to go. I write directly to the file without taking temporary files. I want to replace the beginning of the line in .h and .cpp files with but not in .bak files.

How can you make efficient replacement? Note: I am using GNU sed.

I tried Terdon's command and the insertion is applied to wrong files:

$ cat test.sh 
gfind /tmp/ -type f   \
    \( -name "*.h" -o -name "*.cpp" -o ! -name "*.bak" \) \
    -exec gsed -i '1s/^/#include <stdint.h>\n/' {} +    
$ sh test.sh 
$ cat test.sh    
#include <stdint.h>
gfind /tmp/ -type f   \
    \( -name "*.h" -o -name "*.cpp" -o ! -name "*.bak" \) \
    -exec gsed -i '1s/^/#include <stdint.h>\n/' {} +

where all commands are GNU: find and sed.

  • 1
    Have you read man find and the -exec section? Did you try this and see the error it returned? – terdon Jun 29 '15 at 11:50
  • @terdon I propose to add {} + to the end or even better to use instead xargs, but still something missing. – Léo Léopold Hertz 준영 Jun 29 '15 at 12:01
  • 1
    That is not the command I told you to run. You have added an -o before the ! so it is finding either files ending in .h or files ending in .cpp, or files not ending in .bak. – terdon Jun 29 '15 at 12:33
  • @terdon My mistake. I am sorry for that. I just remove -o in front of ! and I think everything should be ok. – Léo Léopold Hertz 준영 Jun 29 '15 at 12:35

Try this:

find /tmp/ -type f  -name "*.h" -o -name "*.cpp"  \
           -exec  sed -i '1s/^/#include <stdint.h>\n/' {} +

Also, as correctly pointed out to me, the ! -name "*.bak" is superfluous. The -name *foo pattern only matches files ending with foo. Therefore, the *.cpp and *.h already exclude *.bak.

  • Why {} \;? But not {} +? – Léo Léopold Hertz 준영 Jun 29 '15 at 12:11
  • @Masi well, my GNU find can deal with sed -i 's/foo/bar/ * on multiple files correctly (I have edited to use +). I didn't use it at first because I'm not sure that non-GNU sed can do that. – terdon Jun 29 '15 at 12:18
  • @Masi what command did you run? There is no _ there so I don't see how that message could have come from the one I show. – terdon Jun 29 '15 at 12:22
  • Error sed: 1: "/tmp/ ...": bad flag in substitute command: '_' only in BSD sed but not in GNU sed. I think it is enough to stay in GNU Sed. – Léo Léopold Hertz 준영 Jun 29 '15 at 12:22
  • 1
    @Masi try pasting the exact command I gave you. I also removed the unneeded ! -name "*.bak". – terdon Jun 29 '15 at 12:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.