Question

I have a file that contains this kind of paths:

C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c

And I would like to get the following file:

C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c

Note that the non matching path should not be modified.

I know how to do this with sed for a fixed number of subdir, but a variable number is giving me trouble. Actually, I would have to use many s/x/y/ expressions (as many as the max depth... not very elegant).

May be with awk, but this kind of magic is beyond my skills.

FYI, I need this trick to correct some gcov binary files on a cygwin platform.


I am dealing with binary files; therefore, I might have the following kind of data:

bindata\bindata%bindataC:\good\foo.c

which should be translated as:

bindata\bindata%bindataC:/good/foo.c

The first \ must not be translated, despite that it is on the same line.

However, I have just checked my .gcno files while editing this text and it looks like all the paths are flanked with zeros, so most of the answers below should fit.

Was it helpful?

Solution

sed -e '/^C:\\good/ s/\\/\//g' input_file.txt

OTHER TIPS

I would recommend you look into the cygpath utility, which converts path names from one format to another. For instance on my machine:

$ cygpath `pwd`
/home/jericson

$ cygpath -w `pwd`
D:\root\home\jericson

$ cygpath -m `pwd`
D:/root/home/jericson

Here's a Perl implementation of what you asked for:

$ echo 'C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c' | perl -pe 's|\\|/|g if /good/'
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c

It works directly with the string, so it will work anywhere. You could combine it with cygpath, but it only works on machines that have that path:

perl -pe '$_ = `cygpath -m $_` if /good/'

(Since I don't have C:\good on my machine, I get output like C:goodfoo.c. If you use a real path on your machine, it ought to work correctly.)

You want to substitute '/' for all '\' but only on the lines that match the good directory path. Both sed and awk will let you do this by having a LHS (matching) expression that only picks the lines with the right path.

A trivial sed script to do this would look like:

/[Cc]:\\good/ s/\\/\//g

For a file:

c:\bad\foo
c:\bad\foo\bar
c:\good\foo
c:\good\foo\bar

You will get the output below:

c:\bad\foo
c:\bad\foo\bar
c:/good/foo
c:/good/foo/bar

Here's how I would do it in awk:

# fixpaths.awk
/C:\\good/ {
   gsub(/\\/,"/",$1);
   print $1 >> outfile;
}

Then run it using the command:

awk -f fixpaths.awk paths.txt; mv outfile paths.txt

Or with some help from good ol' Bash:

#!/bin/bash

cat file | while read LINE
do
        if <bad_condition>
        then
                echo "$LINE" >> newfile
        else
                echo "$LINE" | sed -e "s/\\/\//g" >> newfile
        fi
done

try this

sed -re '/\\good\\/ s/\\/\//g' temp.txt

or this

awk -F"\\" '{if($2=="good"){OFS="\/"; $1=$1;} print $0}' temp.txt

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top