web-dev-qa-db-fra.com

Recherche récursive et remplacement dans les fichiers texte sur Mac et Linux

Dans le shell Linux, la commande suivante recherchera et remplacera de manière récursive toutes les instances de 'ceci' par 'cela' (je n'ai pas de shell Linux devant moi, mais cela devrait suffire).

find . -name "*.txt" -print | xargs sed -i 's/this/that/g'

À quoi ressemblera une commande similaire sur OSX?

97
Jack

OS X utilise une combinaison d'outils BSD et GNU, il est donc préférable de toujours vérifier la documentation (même si je l'avais dit que less n'était même pas conforme à la page de manuel OS X): 

https://developer.Apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/sed.1.html

sed prend l'argument après -i comme extension des sauvegardes. Fournissez une chaîne vide (-i '') pour aucune sauvegarde.

Ce qui suit devrait faire:

find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +

Le -type f est juste une bonne pratique; sed se plaindra si vous lui donnez un répertoire ou autre .-exec est préférable à xargs; vous n'avez pas besoin de vous préoccuper de -print0 ou de n'importe quoi . Le {} + à la fin signifie que find ajoutera tous les résultats en tant qu'arguments à une instance de la commande appelée, au lieu de la réexécuter à chaque résultat. Une exception concerne le nombre maximal d’arguments de ligne de commande autorisés par le système d’exploitation; dans ce cas, find exécutera plusieurs instances.)

206
TaylanUB

Pour le mac, une approche plus similaire serait la suivante:

find . -name '*.txt' -print0 | xargs -0 sed -i "" "s/form/forms/g"
109
Will

Comme solution alternative, j'utilise celui-ci sur Mac OSX 10.7.5

grep -ilr 'old-Word' * | xargs -I@ sed -i '' 's/old-Word/new-Word/g' @

Le crédit va à: La réponse de Todd Cesere

11
Maciej Gurban

Sur Mac OSX 10.11.5, cela fonctionne bien:

grep -rli 'old-Word' * | xargs -I@ sed -i '' 's/old-Word/new-Word/g' @
10
madx

Aucune de ces solutions ne fonctionne sur OSX.

Faites ce qui suit:

Perl -pi -w -e 's/SEARCH_FOR/REPLACE_WITH/g;' *.txt
7
eb80

Une version qui fonctionne à la fois sous Linux et Mac OS X (en ajoutant le commutateur -e à sed):

export LC_CTYPE=C LANG=C
find . -name '*.txt' -print0 | xargs -0 sed -i -e 's/this/that/g'
7
vroc

Ceci est mon réalisable. sur mac OS X 10.10.4

grep -e 'this' -rl . | xargs sed -i '' 's/this/that/g'

Ceux ci-dessus utilisent find changeront les fichiers qui ne contiennent pas le texte recherché (ajoutez une nouvelle ligne à la fin du fichier), qui est détaillé.

1
NoteCode

Si vous utilisez un terminal zsh, vous pouvez utiliser la magie générique:

sed -i "" "s/search/high-replace/g" *.txt

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

Référez-vous ici pour plus d'informations.

0
user2725109

https://bitbucket.org/masonicboom/serp est un utilitaire indépendant (multiplate-forme), testé sur OSX, qui effectue une recherche et un remplacement récursifs du texte dans les fichiers d'un répertoire remplacement. C'est nouveau, donc pourrait être buggy.

L'utilisation ressemble à:

$ ls test
a  d  d2 z
$ cat test/z
hi
$ ./serp --root test --search hi --replace bye --pattern "*"                         
test/z: replace hi with bye? (y/[n]) y
$ cat test/z
bye
0
user4425237

Chaque fois que je tape cette commande, j'ai toujours l’impression de l’arrêter ou d’oublier un drapeau. J'ai créé un Gist sur github basé sur la réponse de TaylanUB qui effectue une recherche globale à partir du répertoire actuel. Ceci est spécifique à Mac OSX.

https://Gist.github.com/nateflink/9056302

C'est bien parce que je viens d'ouvrir un terminal, puis de le copier dans:

curl -s https://Gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "remplacer-a-url.com"

Vous pouvez obtenir des erreurs de séquence d'octets étranges, alors voici le code complet:

#!/bin/bash
#By Nate Flink

#Invoke on the terminal like this
#curl -s https://Gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

if [ -z "$1" ] || [ -z "$2" ]; then
  echo "Usage: ./$0 [find string] [replace string]"
  exit 1
fi

FIND=$1
REPLACE=$2

#needed for byte sequence error in ascii to utf conversion on OSX
export LC_CTYPE=C;
export LANG=C;

#sed -i "" is needed by the osx version of sed (instead of sed -i)
find . -type f -exec sed -i "" "s|${FIND}|${REPLACE}|g" {} +
exit 0
0
Nate Flink

J'ai utilisé ce format - mais ... j'ai découvert que je devais l'exécuter trois fois ou plus pour qu'il change réellement toutes les instances que je trouvais extrêmement étranges. L'exécuter une fois changerait certains dans chaque fichier mais pas tous. Exécuter exactement la même chaîne deux à quatre fois intercepterait toutes les instances.

find . -type f -name '*.txt' -exec sed -i '' s/thistext/newtext/ {} +
0
user1399145