2

Trying to answer Using Bash/Perl to modify files based on each file's name I ended in a point in which I don't know how to use find and sed all together.

Let's say there is a certain structure of files in which we want to change a line, appending the name of the file.

If it was a normal for loop we would do:

for file in dir/*
do
   sed -i "s/text/text plus $file/g" $file
done

But let's say we want to use find to change files from all subdirectories. In this case, I would use...

find . -type f -exec sed -i "s/text/text plus {}/g" {} \;
                                              ^
                                   it does not like this part

but these {} within sed are not accepted and I get the error

sed: -e expression #1, char 20: unknown option to `s'

I found some similar questions (1) but could not generalize it enough to make it understandable for me in this case.

I am sure you guys will come with a great solution for this. Thanks!

Community
  • 1
  • 1
fedorqui
  • 275,237
  • 103
  • 548
  • 598

2 Answers2

6

I really think the issue is that your files name contains a / that is why sed believes it start the options strings.

Replace / by @ in you sed command would do the job.

I try that on Linux BASH and it work perfectly

find . -type f -exec sed -i -e "s@text@test plus {}@g" {} \;
devnull
  • 118,548
  • 33
  • 236
  • 227
Laurent
  • 61
  • 1
  • Thanks @Laurent, I didn't notice that! Your answer was very helpful. I am finally trying to make it work using `basename` as indicated in the comment to devnull's answer. If you see the way to do so it will be very welcome as well :) – fedorqui Jul 22 '13 at 14:11
4

find would return pathnames (relative or absolute) depending upon the path you specify.

This would conflict with the delimiter you've specified, i.e. /. Change the delimiter for sed and you should be good:

find . -type f -exec sed -i "s|text|text plus {}|g" {} \;

EDIT: For removing the leading ./ from the paths, you can try:

find . -type f -exec sh -c '$f={}; f=${f/.\//}; sed -i "s|text|text plus ${f}|g" {}' \;

I'm certain that better solutions might exist ...

devnull
  • 118,548
  • 33
  • 236
  • 227
  • Oh that's very clever @devnull . I thought it was a problem with `sed` itself. Thanks for the good explanation. Replacing `{}` with `$(basename {})` I still get the `./`. Any way to delete this part? – fedorqui Jul 22 '13 at 14:00
  • That's it, thanks! As the final solution is pretty similar to the one required in the initial question I came from http://stackoverflow.com/q/17788236/1983854, I would suggest you and Laurent to answer that one as me doing it would be kind of copying your answers. – fedorqui Jul 22 '13 at 14:24