La commande sed sur plusieurs fichiers

C'est quoi sed ?

sed est un éditeur de flux. Concrètement, il permet de transformer du texte venant d'un flux (un fichier ou un tube de communication inter-processus). Il est efficace et s'utilise en ligne de commande. C'est un des programmes spécifiés dans POSIX (il est donc disponible de base sur GNU/Linux et les BSD).

Remplacer dans un fichier avec sed

Pour une raison ou une autre, vous devez remplacer une chaine de caractères par une autre dans un fichier contenant du texte brut, cela tombe bien, sed c'est le faire. Par exemple, pour remplacer "ancienne" par "nouvelle" dans un premier fichier et mettre le résultat dans un second fichier, la commande suivante fait le travail : sed -e 's/ancienne/nouvelle/g' fichier1.txt > fichier2.txt. Mais vous voulez peut-être remplacer directement dans le fichier, sed peut encore une fois être un précieux compagnon (grâce à son option --in-place qui est -i en version courte) : sed -i 's$http://vieux.fr$https://nouveau.fr$g' fichier.txt. Au besoin, il est capable de faire une sauvegarde de l'ancien fichier, il suffit pour cela de coller un suffixe à l'option, par exemple avec le suffixe ".bak" (pour backup) : sed -i.bak 's$vieux$nouveau$g' doc.txt.

Plusieurs fichiers d'un coup

Script shell

On peut se faire un petit script shell pour appeler sed sur plusieurs fichiers. Ce n'est pas bien compliqué, mais ce n'est pas très pratique.

for filepath in *
do
  if test -f "$filepath"
  then
    sed -i 's/ancien/nouveau/g' "$filepath"
  fi
done

Combiner sed et find

Qu'est ce que find ?

find a pour fonction de rechercher des fichiers sans s'appuyer sur le contenu. Le plus courant est de le faire rechercher en fonction du nom (potentiellement via une expression régulière, aussi appelée regex). Cependant il gère d'autres propriétés pour filtrer sa recherche (comme la date de modification et les permissions). Il peut appliquer des opérations sur les fichiers : les afficher (dans divers formats), les supprimer, ou exécuter n'importe quelle commande dessus. C'est une commande POSIX (qui est donc très propablement pré-installé sur votre distribution GNU/Linux ou BSD préférée).

Comment utiliser find ?

Pour en savoir plus, RTFM (Read The Fucking Manual, ce qui en français donne : lisez le putain de manuel). Pour cela, vous pouvez utilisez (dans un terminal textuelle) man find ou info find. Si vous voulez passer votre vie dans Emacs, il y a M-x man RET find et M-x info-display-manual RET find (avec "M" étant la touche méta qui est souvent la touche Alt et "RET" pour Entrée).

find tout seul

find a une option -exec. Celle-ci permet d'exécuter une commande sur les fichiers que find a trouvé. Un caractère point-virgule sert à lui indiquer la fin de commande (il faut penser à l'échapper ou le mettre entre guillemets sinon votre shell va l'interpréter) et "{}" sera remplacer par le nom du fichier. Ainsi, vous pouvez supprimer tous les fichiers du dossier courant avec find . -type f -exec rm -i {} \; (vous me direz que rm se serait très bien débrouillé tout seul mais je n'étais pas inspiré pour trouver un exemple simple). Plutôt qu'exécuter la commande à chaque fichier, vous préfériez l'exécuter qu'une fois pour tous : il suffit de remplacer le point-virgule par le signe plus (ce qui, en reprennant l'exemple précédent, donne find . -type f -exec rm -i {} +).

Utilisons maintenant notre ami sed (quoi ? vous doutez que l'on puisse être ami avec un programme informatique ?). Vous devriez deviner comme combiner find et sed. Mais au cas où ce ne serait pas le cas, prenons un exemple. Votre super site web personnel était accessible uniquement en HTTP, mais il y a maintenant du HTTPS pour la vie privée de vos visiteurs et visiteuses. Mais vous avez mis un lien vers votre site web personnel dans le pied de page de votre site web sur le logiciel libre ou Emacs (qui est tellement mieux que vim…). Diantre, tant de fichiers HTML à modifier, heureusement sed et find sont là : find . -type f -iname '*.html' -exec sed -i 's$http://monsiteweb.fr/$https://monsiteweb.fr/$g' {} \;. Alors, oui, l'exemple est encore pourri, car vous utilisez un générateur de site web statique ou un programme générateur de site web (expression fourre-tout pour inclure tout ce qui n'est pas statique, des bêtes include en PHP à une usine à gaz comme WordPress), mais il a le mérite d'exister et d'avoir permis d'inclure un petit troll au passage.

find avec xargs

xargs est une commande POSIX qui permet de construire et exécuter des commandes en utilisant l'entrée standard (stdin en langage C et std::cin en C++). Si on voulait faire la même chose que dans l'exemple avec find et son option -exec, on ferait la commande suivante : find . -type f -iname '*.html' | xargs sed -i 's$http://monsiteweb.fr/$https://monsiteweb.fr/$g'.