web-dev-qa-db-fra.com

commande sed en marche à sec

Je ne suis pas en mesure de savoir si et comment il est possible de faire un run à sec avec sed.

J'ai donc cette commande:

find ./ -type f | xargs sed -i 's/string1/string2/g'

Mais avant de vraiment substituer dans tous les fichiers, je veux vérifier ce que cela remplacerait. Copier toute la structure du répertoire pour vérifier n'est pas une option!

Merci pour tout commentaire (négatif ou positif :))

47
dmeu

Retirer le -i et le diriger vers less pour paginer les résultats. Alternativement, vous pouvez rediriger le tout vers un gros fichier en supprimant le -i et en ajoutant > dryrun.out

Je dois noter que votre script échouera lamentablement avec des fichiers qui contiennent des espaces dans leur nom ou d'autres caractères néfastes comme les nouvelles lignes ou autres. Une meilleure façon de procéder serait:

while IFS= read -r -d $'\0' file; do
  sed -i 's/string1/string2/g' "$file"
done < <(find ./ -type f -print0)
32
SiegeX

Je préférerais utiliser l'option p:

find ./ -type f | xargs sed 's/string1/string2/gp'

Peut être combiné avec le paramètre --quiet pour une sortie moins détaillée:

find ./ -type f | xargs sed --quiet 's/string1/string2/gp'

De man sed:

p:

Imprimez l'espace de motif actuel.

--silencieux:

supprimer l'impression automatique de l'espace du motif

15
Murmel

Je sais que c'est un fil très ancien et que l'OP n'a pas vraiment besoin de cette réponse, mais je suis venu ici à la recherche d'un mode de fonctionnement à sec moi-même, alors j'ai pensé ajouter le conseil ci-dessous pour tous ceux qui viendront ici à l'avenir. Ce que je voulais faire était d'éviter de piétiner le fichier de sauvegarde à moins que quelque chose ne change vraiment. Si vous exécutez aveuglément sed en utilisant le -i option avec suffixe de sauvegarde, le fichier de sauvegarde existant est écrasé, même s'il n'y a rien de substitué.

La façon dont j'ai fini par le faire est de diriger la sortie de sed vers diff et de voir si quelque chose a changé, puis de réexécuter sed avec l'option de mise à jour sur place, quelque chose comme ceci:

if ! sed -e 's/string1/string2/g' $fpath | diff -q $fpath - > /dev/null 2>&1; then
    sed -i.bak -e 's/string1/string2/g' $fpath
fi

Selon la question de l'OP, si l'exigence est de voir ce qui changerait, alors au lieu d'exécuter le sed dans le rythme, vous pouvez refaire le diff avec quelques messages informatifs:

if ! sed -e 's/string1/string2/g' $fpath | diff -q $fpath - > /dev/null 2>&1; then
    echo "File $fpath will change with the below diff:"
    sed -e 's/string1/string2/g' $fpath | diff $fpath -
fi

Vous pouvez également capturer la sortie dans une variable pour éviter de le faire deux fois:

diff=$(sed -e 's/string1/string2/g' $fpath | diff $fpath -)
if [[ $? -ne 0 ]]; then
    echo "File $fpath will change with the below diff:"
    echo "$diff"
fi
6
haridsv