web-dev-qa-db-fra.com

Comment utiliser les noms de fichier dans une commande sed?

J'ai un certain nombre de fichiers .conf qui sont identiques et dans le même répertoire, à l'exception des noms de fichiers différents. Dans chaque fichier .conf portant un nom unique, j'aimerais remplacer un jeu de caractères dans le fichier par le nom du fichier. Par exemple:

Actuellement dans tous les fichiers:

datafname = example.nex
ofprefix = best.example

Débit idéal:

Nom de fichier: 25.conf

datafname = 25.nex
ofprefix = best.25

Nom de fichier: 26.conf

datafname = 26.nex
ofprefix = best.26

J'ai pensé que je pourrais utiliser sed pour parcourir tous ces fichiers afin de trouver et remplacer la chaîne de texte par le nom de fichier en utilisant quelque chose comme:

sed -i conf 's/example/echo $f/g' *

mais cela ne fonctionne pas correctement. Quelqu'un pourrait-il avoir une suggestion sur la façon de procéder?

6
foolsparadise

Tu peux faire:

for f in *.conf; do
    base=$(basename "$f" '.conf') # gives '25' from '25.conf'
    sed -i.before "s/example/$base/g" "$f"
done

Lorsque vous utilisez le commutateur -i en sed, vous devez être absolument sûr que votre commande sed fonctionne car -i modifie les fichiers in-place. Cela signifie que la sortie générée remplacera le fichier d'entrée. Si votre commande de remplacement (s/…/…/) est incorrecte, vous risquez de vous retrouver avec des fichiers vides et aucune sauvegarde. J'ai donc utilisé -i.before qui laissera un fichier *.before avec le contenu d'origine.

8
PerlDuck

Vous pouvez utiliser une boucle for pour parcourir les fichiers. Utilisez le paramètre expansion pour supprimer l’extension de fichier. Utilisez des guillemets autour de l'expression, sinon la variable ne serait pas développée.

#! /bin/bash
for f in *.conf ; do
    b=${f%.conf}
    sed -i "s/example/$b/" "$f"
done
5
choroba

Vous pouvez effectuer la tâche sans boucle en utilisant GNU parallelInstall parallel :

parallel sed -i.old s/example/{.}/ {} ::: *.conf

Ceci est particulièrement utile si vous avez un lot de fichiers à modifier, car parallelexécute un travail par cœur de la CPU.

  • -i.old signifie: éditez le fichier iname__n-place et faites une sauvegarde en ajoutant l'extension .old au nom de fichier d'origine (supprimez .old si vous ne voulez pas de sauvegarde, mais n'oubliez pas que vous n'avez pas de sauvegarde).
  • s/example/{.}/g signifie sname__substitute exampleavec le nom de fichier en entrée sans son extension ({.}) et faites-le gname__lobally (= à chaque occurrence)
  • {} est remplacé par le nom du fichier d'entrée
  • ::: sépare la commande à exécuter des arguments à lui transmettre
  • *.conf correspond à chaque fichier .conf du répertoire en cours
2
dessert

Avec awk, qui a une variable FILENAME définie automatiquement sur le nom du fichier (et, si GNU awk, avec des modifications sur place également):

$ for i in {20..26}; do printf "%s\n" "datafname = example.nex" "ofprefix = best.example" > $i.conf; done
$ gawk -i inplace 'FNR == 1 {split(FILENAME, file, ".")} {gsub("example", file[1])} 1' *.conf
$ cat 25.conf
datafname = 25.nex
ofprefix = best.25
  • FNR == 1 {split(FILENAME, file, ".")}: sur la première ligne de chaque fichier, divisez le nom de fichier sur . et stockez-le dans le tableau file
  • {gsub("example", file[1])} 1: pour toutes les lignes, remplacez example par le premier élément du tableau file et imprimez.
1
muru