Substitution de chemin d'accès DOS vers UNIX dans un fichier
Question
J'ai un fichier qui contient ce type de chemins:
C:\bad\foo.c
C:\good\foo.c
C:\good\bar\foo.c
C:\good\bar\[variable subdir count]\foo.c
Et j'aimerais obtenir le fichier suivant:
C:\bad\foo.c
C:/good/foo.c
C:/good/bar/foo.c
C:/good/bar/[variable subdir count]/foo.c
Notez que le chemin qui ne correspond pas ne doit pas être modifié.
Je sais comment faire cela avec sed pour un nombre fixe de sous-répertoires, mais un nombre variable me pose problème. En fait, je devrais utiliser de nombreuses s/x/y/
expressions (autant que la profondeur maximale ... pas très élégante).
Peut-être avec awk, mais ce genre de magie dépasse mes compétences.
Pour info, j'ai besoin de cette astuce pour corriger certains fichiers binaires gcov sur une plateforme cygwin.
Je traite de fichiers binaires; par conséquent, je pourrais avoir le type de données suivant:
bindata\bindata%bindataC:\good\foo.c
qui devrait être traduit par:
bindata\bindata%bindataC:/good/foo.c
Le premier \
ne doit pas être traduit, même s'il se trouve sur la même ligne.
Cependant, je viens de vérifier mes .gcno
fichiers lors de la modification de ce texte. Il semble que tous les chemins soient flanqués de zéros. La plupart des réponses ci-dessous doivent donc correspondre.
La solution
sed -e '/^C:\\good/ s/\\/\//g' input_file.txt
Autres conseils
Je vous conseillerais de consulter l'utilitaire cygpath
, qui convertit les noms de chemins d'un format à un autre. Par exemple sur ma machine:
$ cygpath `pwd`
/home/jericson
$ cygpath -w `pwd`
D:\root\home\jericson
$ cygpath -m `pwd`
D:/root/home/jericson
Voici une implémentation Perl de ce que vous avez demandé:
$ 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
Cela fonctionne directement avec la chaîne, donc cela fonctionnera n'importe où. Vous pouvez le combiner avec C:goodfoo.c
, mais cela ne fonctionne que sur les machines ayant ce chemin:
perl -pe '$_ = `cygpath -m $_` if /good/'
(Comme je n’ai pas bien C: \ bien sur ma machine, j’obtiens une sortie du type <=>. Si vous utilisez un chemin réel sur votre machine, cela devrait fonctionner correctement.)
Vous souhaitez remplacer "/
" par "\
" mais uniquement sur les lignes correspondant au bon chemin de répertoire. Sed et awk vous permettront de le faire en utilisant une expression LHS (correspondante) qui ne sélectionne que les lignes avec le bon chemin.
Un script sed trivial pour cela ressemblerait à ceci:
/[Cc]:\\good/ s/\\/\//g
Pour un fichier:
c:\bad\foo
c:\bad\foo\bar
c:\good\foo
c:\good\foo\bar
Vous obtiendrez le résultat ci-dessous:
c:\bad\foo
c:\bad\foo\bar
c:/good/foo
c:/good/foo/bar
Voici comment je le ferais dans awk:
# fixpaths.awk
/C:\\good/ {
gsub(/\\/,"/",$1);
print $1 >> outfile;
}
Exécutez-le ensuite à l'aide de la commande suivante:
awk -f fixpaths.awk paths.txt; mv outfile paths.txt
Ou avec l'aide du bon vieux 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
essayez ceci
sed -re '/\\good\\/ s/\\/\//g' temp.txt
ou ceci
awk -F"\\" '{if($2=="good"){OFS="\/"; $1=$1;} print $0}' temp.txt