Comment trouver et remplacer chaque occurrence de:
subdomainA.example.com
avec
subdomainB.example.com
dans chaque fichier texte sous l’arborescence de répertoire /home/www/
récursivement?
Remarque : N’exécutez pas cette commande sur un dossier comprenant un repository git – les modifications apscopes à .git pourraient corrompre votre index git.
find /home/www -type f -print0 | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'
De l’ man find
:
-print0 (GNU find only) indique find pour utiliser le caractère nul (\ 0) au lieu des espaces comme délimiteur de sortie entre les chemins trouvés. C’est une option plus sûre si vos fichiers peuvent contenir des espaces ou d’autres caractères spéciaux. Il est recommandé d’utiliser l’argument -print0 pour trouver si vous utilisez la commande -exec ou xargs (l’argument -0 est nécessaire dans xargs).
Remarque : N’exécutez pas cette commande sur un dossier comprenant un repository git – les modifications apscopes à .git pourraient corrompre votre index git.
find /home/www/ -type f -exec \ sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
Comparé à d’autres réponses, cela est plus simple que la plupart et utilise sed au lieu de perl, ce que demandait la question initiale.
La façon la plus simple pour moi est
grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'
Tous les trucs sont presque les mêmes, mais j’aime bien celui-ci:
find -type f -exec sed -i 's///g' {} +
find
: cherchez dans le répertoire.
-type f
:
Le fichier est de type: fichier normal
-exec command {} +
:
Cette variante de l’action -exec exécute la commande spécifiée sur les fichiers sélectionnés, mais la ligne de commande est créée en ajoutant chaque nom de fichier sélectionné à la fin. le nombre total d’appels de la commande sera bien inférieur au nombre de fichiers correspondants. La ligne de commande est construite de la même manière que xargs construit ses lignes de commande. Une seule instance de {} est autorisée dans la commande. La commande est exécutée dans le répertoire de départ.
cd /home/www && find . -type f -print0 | xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'
Pour moi, la solution la plus simple à retenir est https://stackoverflow.com/a/2113224/565525 , à savoir:
sed -i '' -e 's/subdomainA/subdomainB/g' $(find /home/www/ -type f)
NOTE : -i ''
résout le problème OSX sed: 1: "...": invalid command code .
REMARQUE : S’il y a trop de fichiers à traiter, vous obtiendrez une Argument list too long
. La solution de contournement – utilisez la solution find -exec
ou xargs
décrite ci-dessus.
Pour quiconque utilise un chercheur d’argent ( ag
)
ag SearchSsortingng -l0 | xargs -0 sed -i 's/SearchSsortingng/Replacement/g'
Dans la mesure où ag ignore par défaut les fichiers / dossiers git / hg / svn, cela peut être exécuté en toute sécurité dans un référentiel.
Pour réduire les fichiers à récursivement sed
, vous pouvez rechercher votre instance de chaîne:
grep -rl /path/to/folder | xargs sed -is^ ^^g
Si vous exécutez man grep
vous remarquerez que vous pouvez également définir un --exlude-dir="*.git"
si vous voulez omettre de chercher dans les répertoires .git, en évitant les problèmes d’index git comme d’autres l’ont fait poliment.
Vous conduisant à:
grep -rl --exclude-dir="*.git" /path/to/folder | xargs sed -is^ ^^g
Un oneeliner sympa en extra. Utiliser git grep
git grep -lz 'subdomainA.example.com' | xargs -0 perl -i'' -pE "s/subdomainA.example.com/subdomainB.example.com/g"
Celui-ci est compatible avec les référentiels git, et un peu plus simple:
Linux:
git grep -l 'original_text' | xargs sed -i 's/original_text/new_text/g'
Mac:
git grep -l 'original_text' | xargs sed -i '' -e 's/original_text/new_text/g'
J’avais juste besoin de cela et je n’étais pas satisfait de la rapidité des exemples disponibles. Donc, je suis venu avec le mien:
cd /var/www && ack-grep -l --print0 subdomainA.example.com | xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'
Ack-grep est très efficace pour trouver des fichiers pertinents. Cette commande a remplacé ~ 145 000 fichiers en un clin d’œil alors que les autres ont mis tellement de temps que je ne pouvais plus attendre jusqu’à la fin.
find /home/www/ -type f -exec perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
find /home/www/ -type f
liste tous les fichiers dans / home / www / (et ses sous-répertoires). L’indicateur “-exec” indique find pour exécuter la commande suivante sur chaque fichier trouvé.
perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +
est la commande exécutée sur les fichiers (plusieurs à la fois). Le {}
est remplacé par les noms de fichiers. Le +
à la fin de la commande indique find
pour générer une commande pour de nombreux noms de fichiers.
Par la page de manuel de find
: “La ligne de commande est construite de la même manière que xargs construit ses lignes de commande.”
Il est donc possible d’atteindre votre objective (et de gérer les noms de fichiers contenant des espaces) sans utiliser xargs -0
ou -print0
.
grep -lr 'subdomainA.example.com' | while read file; do sed -i "s/subdomainA.example.com/subdomainB.example.com/g" "$file"; done
J’imagine que la plupart des gens ne savent pas qu’ils peuvent transférer quelque chose dans un fichier “while read” et cela évite ces arguments -print0 désagréables, tout en conservant des espaces dans les noms de fichiers.
L’ajout d’un echo
avant le sed vous permet de voir quels fichiers changeront avant de le faire.
Vous pouvez utiliser awk pour résoudre ceci comme ci-dessous,
for file in `find /home/www -type f` do awk '{gsub(/subdomainA.example.com/,"subdomainB.example.com"); print $0;}' $file > ./tempFile && mv ./tempFile $file; done
J’espère que ceci vous aidera !!!
Essaye ça:
sed -i 's/subdomainA/subdomainB/g' `grep -ril 'subdomainA' *`
#!/usr/local/bin/bash -x find * /home/www -type f | while read files do sedtest=$(sed -n '/^/,/$/p' "${files}" | sed -n '/subdomainA/p') if [ "${sedtest}" ] then sed s'/subdomainA/subdomainB/'g "${files}" > "${files}".tmp mv "${files}".tmp "${files}" fi done
Si cela ne vous dérange pas d’utiliser vim
avec grep
ou de find
outils, vous pouvez suivre la réponse donnée par l’utilisateur Gert dans ce lien -> Comment faire un remplacement de texte dans une hiérarchie de grands dossiers? .
Voici le deal:
grep récursivement pour la chaîne que vous souhaitez remplacer dans un certain chemin, et ne prenez que le chemin complet du fichier correspondant. (ce serait la $(grep 'ssortingng' 'pathname' -Rl)
.
(facultatif) si vous voulez faire une pré-sauvegarde de ces fichiers dans un répertoire centralisé, vous pouvez également utiliser ceci: cp -iv $(grep 'ssortingng' 'pathname' -Rl) 'centralized-directory-pathname'
ensuite vous pouvez éditer / remplacer à volonté dans vim
suivant un schéma similaire à celui fourni sur le lien donné:
:bufdo %s#ssortingng#replacement#gc | update
juste pour éviter de changer aussi
mais rest
(peut-être pas bon dans l’idée de la racine du domaine)
find /home/www/ -type f -exec sed -i 's/\bsubdomainA\.example\.com\b/\1subdomainB.example.com\2/g' {} \;
Selon cet article de blog:
find . -type f | xargs perl -pi -e 's/oldtext/newtext/g;'
Pour Qshell (qsh) sur IBMi, pas bash comme balisé par OP.
Limitations des commandes qsh:
Ainsi la solution dans qsh:
PATH='your/path/here' SEARCH=\'subdomainA.example.com\' REPLACE=\'subdomainB.example.com\' for file in $( find ${PATH} -P -type f ); do TEMP_FILE=${file}.${RANDOM}.temp_file if [ ! -e ${TEMP_FILE} ]; then touch -C 819 ${TEMP_FILE} sed -e 's/'$SEARCH'/'$REPLACE'/g' \ < ${file} > ${TEMP_FILE} mv ${TEMP_FILE} ${file} fi done
Mises en garde:
Si vous voulez utiliser ceci sans détruire complètement votre repository SVN, vous pouvez dire “trouver” pour ignorer tous les fichiers cachés en procédant comme suit:
find . \( ! -regex '.*/\..*' \) -type f -print0 | xargs -0 sed -i 's/subdomainA.example.com/subdomainB.example.com/g'
Combinaison de grep
et de sed
for pp in $(grep -Rl looking_for_ssortingng) do sed -i 's/looking_for_ssortingng/something_other/g' "${pp}" done
Un peu vieille école mais cela a fonctionné sur OS X.
Il y a peu de ruses:
• Ne modifiera que les fichiers avec l’extension .sls
dans le répertoire en cours
• .
doit être échappé pour s’assurer que sed
ne les évalue pas comme “n’importe quel personnage”
• ,
est utilisé comme délimiteur sed
place de l’habituel /
Notez également que cela consiste à éditer un modèle Jinja pour passer une variable
dans le chemin d’une import
(mais ceci est hors sujet).
Tout d’abord, vérifiez que votre commande sed fait ce que vous voulez (cela n’imprimera que les modifications apscopes à stdout, cela ne changera pas les fichiers):
for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done
Modifiez la commande sed selon vos besoins, une fois que vous êtes prêt à apporter des modifications:
for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed -i '' 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done
Notez le -i ''
dans la commande sed , je ne voulais pas créer une sauvegarde des fichiers originaux (comme expliqué dans Modifications sur place avec sed sur OS X ou dans le commentaire de Robert Lujo sur cette page).
Heureux les gens qui sèment!
perl -p -i -e 's/oldthing/new_thingy/g' `grep -ril oldthing *`
pour modifier plusieurs fichiers (et enregistrer une sauvegarde en tant que *.bak
):
perl -p -i -e "s/\|/x/g" *
va prendre tous les fichiers dans le répertoire et remplacer |
avec x appelé une “tarte Perl” (facile comme une tarte)
J’utilise juste des tops:
find . -name '*.[c|cc|cp|cpp|m|mm|h]' -print0 | xargs -0 tops -verbose replace "verify_noerr()" with "__Verify_noErr()" \ replace "check()" with "__Check()"
Une manière plus simple consiste à utiliser le ci-dessous sur la ligne de commande
find /home/www/ -type f|xargs perl -pi -e 's/subdomainA\.example\.com/subdomainB.example.com/g'
C’est la meilleure solution globale que j’ai trouvée pour OSX et Windows (msys2). Devrait fonctionner avec tout ce qui peut obtenir la version GNU de sed. Ignore les répertoires .git pour ne pas corrompre vos sums de contrôle.
Sur mac, installez d’abord coreutils et assurez-vous que gsed est dans le chemin –
brew install coreutils
Ensuite, je colle cette fonction dans mon zshrc / bashrc ->
replace-recursive() { hash gsed 2>/dev/null && local SED_CMD="gsed" || SED_CMD="sed" find . -type f -name "*.*" -not -path "*/.git/*" -print0 | xargs -0 $SED_CMD -i "s/$1/$2/g" } usage: replace-recursive
Pour remplacer tout le contenu correspondant à chaîne_1 par chaîne_2 de tous les fichiers .c et .h dans le répertoire et les sous-répertoires en cours (à l’exception de .git /) .
Cela fonctionne sur Mac :
find . -type f -path "*.git*" -prune -o -name '*\.[ch]' -exec \ sed -i '' -e 's/'$1'/'$2'/g' {} +
Cela devrait fonctionner sous Linux (pas encore testé):
find . -type f -path "*.git*" -prune -o -name '*\.[ch]' -exec \ sed -i 's/ssortingng_1/ssortingng_2/g' {} +
Si vous avez access au nœud, vous pouvez faire un npm install -g rexreplace
, puis
rexreplace 'subdomainA.example.com' 'subdomainB.example.com' /home/www/**/*.*