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?

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.

  • 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 ? – Anonymous12223 Aug 20 '14 at 9:04
  • Indeed! Sorry, don't know how I got rid of that. Fixed now. You do need the -. – Michael Homer Aug 20 '14 at 9:15
  • Yeah, but, still, why does the command take only the last -name in consideration ? Maybe I did something wrong ? – Anonymous12223 Aug 20 '14 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. – Michael Homer Aug 20 '14 at 9:29
  • echo "C:\\" | sed -e 's/C:\\/\/root/g' – c4f4t0r Aug 20 '14 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. :)

  • I'd say 's\\\C:\\\\\\\/root/\\\g' – Anonymous12223 Aug 20 '14 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 '14 at 9:33

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.