J'ai besoin de remplacer une chaîne dans beaucoup de fichiers dans un dossier, avec seulement ssh
accès au serveur. Comment puis-je faire ceci?
461
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Les occurrences de "foo" seront remplacées par "bar".
Sur les systèmes BSD comme macOS, vous devez fournir une extension de sauvegarde comme -i '.bak'
ou bien "risque de corruption ou de contenu partiel" selon la page de manuel.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
,-i
nécessite une chaîne après, qui est ajoutée aux anciens noms de fichiers.sed -i .bak 's/foo/bar/g' *.xx
Déplace donc tous les.xx
fichiers vers le.xx.bak
nom équivalent , puis génère les.xx
fichiers avec la substitution foo → bar.sed -i 's/foo\ with\ spaces/bar/g' *
. Je suppose que vous l'avez découvert après si longtemps ... mais de cette façon, cela reste pour d'autres qui trouvent le même problème.sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Similaire à la réponse de Kaspar mais avec le drapeau g pour remplacer toutes les occurrences sur une ligne.
Pour la casse globale insensible:
la source
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
(voir cet article et celui-ci )--include=*.whatever
avec -r.git/
. Assurez-vous decd
descendre à un niveau inférieur.git status
retourne:error: bad index file sha1 signature.... fatal: index file corrupt
. Ce qui donne?La réponse de @ kev est bonne, mais n'affecte que les fichiers du répertoire immédiat. L'exemple ci-dessous utilise grep pour rechercher récursivement des fichiers. Cela fonctionne pour moi à chaque fois.
Répartition des commandes
grep -r : --recursive , lit récursivement tous les fichiers de chaque répertoire.
grep -l : --print-with-matches , imprime le nom de chaque fichier qui a une correspondance, au lieu d'imprimer les lignes correspondantes.
grep -i : --ignore-case .
xargs : transformez le STDIN en arguments, suivez cette réponse .
La commande xargs -i @ ~ contient @ ~ : un espace réservé pour l'argument à utiliser à une position spécifique dans la commande ~ ~ , le signe @ est un espace réservé qui pourrait être remplacé par n'importe quelle chaîne.
sed -i : éditez les fichiers sur place, sans sauvegardes.
sed s / regexp / remplacement / : chaîne de remplacement correspondant à regexp avec remplacement .
sed s / regexp / remplacement / g : global , faites la substitution pour chaque correspondance au lieu de seulement la première correspondance.
la source
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
, aussi, pourquoi-i
dans la commande xargs? J'ai lu dans le manuel qu'il est obsolète et devrait être utilisé à la-I
place. Et est@
utilisé comme délimiteur pour le début et la fin du motif?grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
) et le@
signe par exempleCela a fonctionné pour moi:
Howerver, cela n'a pas:
sed -i 's/string1/string2/g' *
. Peut-être que "foo" n'était pas censé être string1 et "bar" pas string2.la source
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
Il y a quelques réponses standard à cela déjà listées. En règle générale, vous pouvez utiliser find pour répertorier récursivement les fichiers, puis effectuer les opérations avec sed ou perl .
Pour la plupart des utilisations rapides, vous pouvez trouver que la commande rpl est beaucoup plus facile à retenir. Voici le remplacement (foo -> bar), récursivement sur tous les fichiers:
rpl -R foo bar .
Vous devrez probablement l'installer (
apt-get install rpl
ou similaire).Cependant, pour les tâches plus difficiles qui impliquent des expressions régulières et une substitution arrière, ou des renommages de fichiers ainsi que la recherche et le remplacement, l'outil le plus général et le plus puissant que je connaisse est repren , un petit script Python que j'ai écrit il y a quelque temps pour certains tâches de renommage et de refactoring plus épineuses. Les raisons pour lesquelles vous pourriez préférer ce sont:
Pour l' utiliser,
pip install repren
. Consultez le README pour des exemples.la source
Pour remplacer une chaîne dans plusieurs fichiers, vous pouvez utiliser:
Par exemple
Blog source
la source
Pour remplacer un chemin dans les fichiers (en évitant les caractères d'échappement), vous pouvez utiliser la commande suivante:
Le signe @ signifie que tous les caractères spéciaux doivent être ignorés dans une chaîne suivante.
la source
Si votre chaîne contient une barre oblique (/), vous pouvez remplacer le délimiteur par '+'.
Cette commande s'exécuterait récursivement dans le répertoire en cours.
la source
../domain.com
àdomain.com
Les occurrences de la première ligne de "foo" seront remplacées par "bar". Et vous pouvez utiliser la deuxième ligne pour vérifier.
la source
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
Si vous avez une liste de fichiers que vous pouvez utiliser
Si vous avez tous les fichiers que vous pouvez utiliser
Si vous avez une liste de fichiers avec extension, vous pouvez utiliser
la source
replace "old_string" "new_string" -- *.txt
replace
utilitaire. Sans cette information, cette réponse est incomplète."Vous pouvez également utiliser find et sed, mais je trouve que cette petite ligne de perl fonctionne bien.
"(Extrait de http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
Mes meilleurs résultats proviennent de l'utilisation de perl et grep (pour garantir que le fichier a l'expression de recherche)
la source
Étant donné que vous souhaitez rechercher la chaîne
search
et la remplacer parreplace
plusieurs fichiers, voici ma formule d'une ligne testée au combat :Explication rapide de grep:
-R
- recherche récursive-i
- insensible à la casse-I
- sauter les fichiers binaires (vous voulez du texte, non?)-l
- imprimer une liste simple en sortie. Nécessaire pour les autres commandesLa sortie grep est ensuite dirigée vers sed (via xargs) qui est utilisée pour remplacer réellement le texte. Le
-i
drapeau modifie directement le fichier. Retirez-le pour une sorte de mode "marche à sec".la source
J'ai concocté ma propre solution avant de trouver cette question (et les réponses). J'ai cherché différentes combinaisons de "remplacer" "plusieurs" et "xml", car c'était mon application, mais je n'ai pas trouvé celle-ci en particulier.
Mon problème: j'avais des fichiers xml de printemps avec des données pour les cas de test, contenant des objets complexes. Un refactor sur le code source java a changé beaucoup de classes et ne s'est pas appliqué aux fichiers de données xml. Afin de sauvegarder les données des cas de test, j'ai dû changer tous les noms de classe dans tous les fichiers xml, répartis sur plusieurs répertoires. Tout en enregistrant des copies de sauvegarde des fichiers xml d'origine (bien que ce ne soit pas un must, car le contrôle de version me sauverait ici).
Je cherchais une combinaison de
find
+sed
, car cela a fonctionné pour moi dans d'autres situations, mais pas avec plusieurs remplacements à la fois.Ensuite, j'ai trouvé la réponse ask ubuntu et cela m'a aidé à construire ma ligne de commande:
Et cela a fonctionné parfaitement (eh bien, mon cas avait six remplacements différents). Mais veuillez noter qu'il touchera tous les fichiers * .xml dans le répertoire actuel. Pour cette raison, et si vous êtes responsable devant un système de contrôle de version, vous voudrez peut-être filtrer en premier et ne transmettre qu'à
sed
ceux qui ont réellement les chaînes que vous voulez; comme:la source
findstr /spin /c:"quéquieresbuscar" *.xml
ce sera pratique.la source
Vraiment boiteux, mais je n'ai pu faire fonctionner aucune des commandes sed sur OSX, j'ai donc fait cette chose stupide à la place:
^ - copiez ces trois lignes dans mon presse-papiers (oui, incluez la nouvelle ligne de fin), puis:
vi *
et maintenez la commande-v jusqu'à ce qu'il indique qu'il n'y a plus de fichiers.
Dumb ... hacky ... efficace ...
la source
Sur un MacBook Pro, j'ai utilisé ce qui suit (inspiré de https://stackoverflow.com/a/19457213/6169225 ):
la source
-e
indique simplement à sed que le prochain jeton est une commande. Pour les expressions régulières étendues, utilisez-E
plutôt.L'éditeur de flux modifie plusieurs fichiers «sur place» lorsqu'il est appelé avec le
-i
commutateur, ce qui prend un fichier de sauvegarde se terminant en argument. Doncremplace
foo
parbar
dans tous les fichiers de ce dossier, mais ne descend pas dans les sous-dossiers. Cela va cependant générer un nouveau.bak
fichier pour chaque fichier de votre répertoire. Pour ce faire de manière récursive pour tous les fichiers de ce répertoire et tous ses sous-répertoires, vous avez besoin d'un assistant, commefind
, pour parcourir l'arborescence des répertoires.find
vous permet des restrictions supplémentaires sur les fichiers à modifier, en spécifiant d'autres arguments commefind ./ -name '*.php' -or -name '*.html' -print0
, si nécessaire.Remarque: GNU
sed
ne nécessite pas de fin de fichier,sed -i 's/foo/bar/g' *
fonctionnera également; FreeBSDsed
demande une extension, mais permet un espace entre les deux, donc çased -i .bak s/foo/bar/g *
marche.la source
script pour la commande multiedit
D'après la réponse de Kaspar, j'ai créé un script bash pour accepter les arguments de ligne de commande et éventuellement limiter les noms de fichiers correspondant à un modèle. Enregistrez dans votre $ PATH et rendez exécutable, puis utilisez simplement la commande ci-dessus.
Voici le script:
la source
Si le fichier contient des barres obliques inverses (chemins généralement), vous pouvez essayer quelque chose comme ceci:
ex:
la source
Pour maintenir mon nœud anglais personnel, j'ai écrit un script utilitaire qui aide à remplacer plusieurs paires d'anciennes / nouvelles chaînes, pour tous les fichiers d'un répertoire de manière récursive.
Les multiples paires d'anciennes / nouvelles chaînes sont gérées dans une carte de hachage.
Le répertoire peut être défini via la ligne de commande ou la variable d'environnement, la carte est codée en dur dans le script, mais vous pouvez modifier le code à charger à partir d'un fichier, si nécessaire.
Il nécessite bash 4.2, en raison d'une nouvelle fonctionnalité.
en_standardize.sh:
la source
Utiliser la commande ack serait beaucoup plus rapide comme ceci:
Aussi si vous avez un espace blanc dans le résultat de la recherche. Vous devez y échapper.
la source
Je donne un exemple pour corriger une erreur de shebang commune dans les sources python.
Vous pouvez essayer l'approche grep / sed. En voici un qui fonctionne avec GNU sed et ne cassera pas un dépôt git:
Ou vous pouvez utiliser greptile :)
Je viens de tester le premier script, et le second devrait également fonctionner. Soyez prudent avec les caractères d'échappement, je pense qu'il devrait être plus facile d'utiliser greptile dans la plupart des cas. Bien sûr, vous pouvez faire beaucoup de choses intéressantes avec sed, et pour cela il peut être préférable de maîtriser son utilisation avec xargs.
la source
J'ai trouvé celui-ci dans un autre article (je ne me souviens pas lequel) et bien qu'il ne soit pas le plus élégant, il est simple et en tant qu'utilisateur Linux novice, cela ne m'a posé aucun problème
si vous avez des espaces ou d'autres caractères spéciaux, utilisez un \
pour les chaînes dans les sous-répertoires, utilisez **
la source
La commande ci-dessous peut être utilisée pour rechercher d'abord les fichiers et remplacer les fichiers:
Par exemple
la source
Il existe un moyen plus simple d'utiliser un simple fichier de script:
ouvrez le fichier dans gedit ou un éditeur de votre choix, j'utilise ici gedit.
Ensuite, dans l'éditeur, collez ce qui suit dans le fichier
Enregistrez le fichier, fermez gedit , puis quittez votre terminal ou fermez-le et démarrez-le pour pouvoir charger le nouveau script que vous avez ajouté.
Accédez au répertoire dans lequel vous souhaitez modifier plusieurs fichiers. Exécutez ensuite:
Appuyez sur Entrée et cela remplacera automatiquement oldstring et oldstring1 dans tous les fichiers qui les contiennent respectivement avec newstring et newstring1 corrects .
Il sautera tous les répertoires et fichiers qui ne contiennent pas les anciennes chaînes.
Cela pourrait aider à éliminer le travail fastidieux de la saisie au cas où vous disposez de plusieurs répertoires avec des fichiers qui nécessitent un remplacement de chaîne. Tout ce que vous avez à faire est de naviguer vers chacun de ces répertoires, puis d'exécuter:
#replace_string_files_present_dir
Tout ce que vous avez à faire est de vous assurer que vous avez inclus ou ajouté toutes les chaînes de remplacement comme je vous l'ai montré ci-dessus:
replace "oldstring" "newstring" -- *
à la fin du fichier / bin / replace_string_files_present_dir .
Pour ajouter une nouvelle chaîne de remplacement, ouvrez simplement le script que nous avons créé en tapant ce qui suit dans le terminal:
sudo gedit /bin/replace_string_files_present_dir
Ne vous inquiétez pas du nombre de chaînes de remplacement que vous ajoutez, elles n'auront aucun effet si l' ancienne chaîne n'est pas trouvée.
la source
.gitlab-ci.yml
ou atravis.yml
). Chaque virage consistant à écrire un script pour l'exécuter plus tard est un anti-modèle, car vous devrez ensuite scripter la création du script (et je$ remplace "From" "To" - `find / path / to / folder -type f`
(replace - un utilitaire de remplacement de chaîne du système de base de données MySQL)
la source