4

I've been trying to create a script that would replace every occurence of C:\ in two different types of file by /root.

My arborescence looks like :

- Batch
  - Place of the script
- Conf
  - Appli1
    - File1.xml
    - File2.xml
    - ...
  - Appli2
    - File1.xml
    - File2.xml
    - ...
  - ...
- Info
  - File1.conf
  - File2.conf
  - ...

My script is like so in /Batch :

#/bin/bash
find ../ -name "*.xml" -o name "*.conf" -print | xargs sed -i 's C:\ /root/ g'

But, I have an error on the sed part, which says that at character 14: command 's' unfinished

Why is that so?

0

2 Answers 2

4

Where you use:

sed -i 's C:\ /root/ g'

you're using the s command with a space character separating the different parts of the command, which is unusual, but completely valid. When you precede your separator character with a backslash, though, it's not treated as a separator, but as part of the argument itself.

The problem you have here is that the backslash in C:\ is escaping the space in the middle, so s never finds the end of the replacement (which is now g) and complains that the command is unfinished, as you saw.

At the least, you need to escape the backslash itself with another backslash:

sed -i 's C:\\ /root/ g'

This will work, although replacing the spaces with another character might be clearer.


As for your use of xargs and subdirectories - xargs isn't required here, and find can do it, including handling files in subdirectories, on its own. Use:

find ../ \( -name "*.xml" -o -name "*.conf" \) -exec sed -i -e 's|C:\\|/root/|g' '{}' +

to have find run the sed command itself with all the filenames it finds. The filenames are inserted in place of the {}, and + means find will minimise the number of times it runs the command.

-execdir may be better than -exec for certain security reasons outlined in the find man page; it is a non-standard extension, but as you seem to be using GNU tools it should be there for you if you need it.

5
  • There is just one problem. I think you miss a "-" before the name in your command. Without the "-" I get an error for badly using the command. When I put the both "-o -names", the command only takes the last one ... is it normal ? Aug 20, 2014 at 9:04
  • Indeed! Sorry, don't know how I got rid of that. Fixed now. You do need the -. Aug 20, 2014 at 9:15
  • Yeah, but, still, why does the command take only the last -name in consideration ? Maybe I did something wrong ? Aug 20, 2014 at 9:17
  • You need to parenthesise the tests: .find ../ \( -name "*.xml" -o -name "*.conf" \), as in the last edit. Sorry, I copied your command down and didn't pay enough attention to that part of it. Otherwise -exec only gets paired up with the second branch. Aug 20, 2014 at 9:29
  • echo "C:\\" | sed -e 's/C:\\/\/root/g'
    – c4f4t0r
    Aug 20, 2014 at 9:32
2

It's the backslash. Backslash defuses the next character and makes it lose special meanings. The sed command is reading what you've typed as (just the sed expression here, I'm not doing the whole tedious shell command line):

s
<SPACE>
C
:
Literal <SPACE>
/root/
<SPACE>

You've told sed that you want to use as the marker for the expression you're looking for, and the replacement. But sed is hoping to see something like:

s
<SPACE>
C
:
Literal \
<SPACE>
/root/
<SPACE>

To make the backslash into a literal backslash, prepend it with a backslash:

sed -e 's C:\\ /root '

Personally, I'd prefer to avoid using a space. I'd use something like |, or ;. But you'd still have a problem with the backslash. What's really fun is working out what you'd have to type to use a backslash as the separator. :)

2
  • I'd say 's\\\C:\\\\\\\/root/\\\g' Aug 20, 2014 at 9:16
  • @xhaltar - You're confusing shell processing and sed processing. Sed sees the backslash as the separator and defuses the special meaning. sed -e 's\c:\foo\' would change c: into foo. You can't actually match the backslash, as a backslash any more. Lose the quotes around the sed expression though, and you need `sed -e s\\c:\\foo\\`, as the backslash is exposed to the shell command processing.
    – JezC
    Aug 20, 2014 at 9:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .