Respuestas:
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Las apariciones de "foo" serán reemplazadas por "bar".
En los sistemas BSD como macOS, debe proporcionar una extensión de respaldo como -i '.bak'
"riesgo de corrupción o contenido parcial" según la página de manual.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
, -i
requiere una cadena después, que se agrega a los nombres de archivo antiguos. Entonces sed -i .bak 's/foo/bar/g' *.xx
mueve todos los .xx
archivos al .xx.bak
nombre equivalente y luego genera los .xx
archivos con la sustitución foo → barra.
sed -i 's/foo\ with\ spaces/bar/g' *
. Supongo que te has enterado después de tanto tiempo ... pero de esta manera queda para que otros encuentren el mismo problema.
sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Similar a la respuesta de Kaspar pero con la bandera g para reemplazar todas las ocurrencias en una línea.
find ./ -type f -exec sed -i 's/string1/string2/g' {} \;
Para mayúsculas y minúsculas:
find ./ -type f -exec sed -i 's/string1/string2/gI' {} \;
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
(vea esta publicación y esta )
--include=*.whatever
con -r
.git/
. Asegúrese de cd
bajar a un nivel inferior.
git status
devuelve: error: bad index file sha1 signature.... fatal: index file corrupt
. ¿Lo que da?
La respuesta de @ kev es buena, pero solo afecta a los archivos en el directorio inmediato. El siguiente ejemplo utiliza grep para buscar archivos de forma recursiva. A mí me funciona siempre.
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
Desglose de comandos
grep -r : --recursivo , lee recursivamente todos los archivos de cada directorio.
grep -l : --print-with-coincide , imprime el nombre de cada archivo que tiene una coincidencia, en lugar de imprimir líneas coincidentes.
grep -i : --ignore-case .
xargs : transforma el STDIN en argumentos, sigue esta respuesta .
El comando xargs -i @ ~ contiene @ ~ : un marcador de posición para el argumento que se utilizará en una posición específica en el comando ~ , el signo @ es un marcador de posición que podría reemplazarse por cualquier cadena.
sed -i : edita archivos en su lugar, sin copias de seguridad.
sed s / regexp / replace / : sustituye la expresión regular de coincidencia de cadenas con reemplazo .
sed s / regexp / replace / g : global , realice la sustitución de cada coincidencia en lugar de solo la primera coincidencia.
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
, también, ¿ -i
por qué en el comando xargs? Leí en el manual que está en desuso y debería usar-I
en lugar. ¿Y se @
usa como delimitador para el principio y el final del patrón?
grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
) y el @
letrero, por ejemplo
Esto funcionó para mí:
find ./ -type f -exec sed -i 's/string1/string2/' {} \;
Howerver, no hizo esto: sed -i 's/string1/string2/g' *
. Tal vez "foo" no estaba destinado a ser string1 y "bar" no a string2.
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
Hay algunas respuestas estándar a esto ya enumeradas. En general, puede usar find para enumerar recursivamente los archivos y luego realizar las operaciones con sed o perl .
Para la mayoría de los usos rápidos, puede encontrar que el comando rpl es mucho más fácil de recordar. Aquí está el reemplazo (foo -> bar), recursivamente en todos los archivos:
rpl -R foo bar .
Probablemente necesites instalarlo (apt-get install rpl
o similar).
Sin embargo, para trabajos más difíciles que involucran expresiones regulares y sustitución hacia atrás, o cambios de nombre de archivos, así como búsqueda y reemplazo, la herramienta más general y poderosa que conozco es la respuesta , un pequeño script de Python que escribí hace un tiempo. tareas de cambio de nombre y refactorización más espinosas. Las razones por las que puede preferirlo son:
Para usarlo, pip install repren
. Consulte el archivo README para ver ejemplos.
Para reemplazar una cadena en varios archivos puede usar:
grep -rl string1 somedir/ | xargs sed -i 's/string1/string2/g'
P.ej
grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'
Para reemplazar una ruta dentro de los archivos (evitando caracteres de escape) puede usar el siguiente comando:
sed -i 's@old_path@new_path@g'
El signo @ significa que todos los caracteres especiales deben ignorarse en la siguiente cadena.
En caso de que su cadena tenga una barra diagonal (/), puede cambiar el delimitador a '+'.
find . -type f -exec sed -i 's+http://example.com+https://example.com+g' {} +
Este comando se ejecutaría recursivamente en el directorio actual.
../domain.com
adomain.com
Las apariciones de la primera línea de "foo" serán reemplazadas por "bar". Y puede usar la segunda línea para verificar.
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
grep 'foo' -r * | awk -F: {'print $1'} | sort -n | uniq -c
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
Si tiene una lista de archivos que puede usar
replace "old_string" "new_string" -- file_name1 file_name2 file_name3
Si tiene todos los archivos que puede usar
replace "old_string" "new_string" -- *
Si tiene una lista de archivos con extensión, puede usar
replace "old_string" "new_string" -- *.extension
replace "old_string" "new_string" -- *.txt
replace
utilidad. Sin esta información, esta respuesta está incompleta.
"También podrías usar find y sed, pero creo que esta pequeña línea de perl funciona muy bien.
perl -pi -w -e 's/search/replace/g;' *.php
"(Extraído de http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
Mis mejores resultados provienen del uso de perl y grep (para asegurar que el archivo tenga la expresión de búsqueda)
perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )
Dado que desea buscar la cadena search
y reemplazarla con replace
varios archivos, esta es mi fórmula de una línea probada en batalla :
grep -RiIl 'search' | xargs sed -i 's/search/replace/g'
Explicación rápida de grep:
-R
- búsqueda recursiva-i
- insensible a mayúsculas y minúsculas-I
- saltar archivos binarios (quieres texto, ¿verdad?)-l
- Imprima una lista simple como salida. Necesario para los otros comandosLa salida grep se canaliza a sed (a través de xargs) que se usa para reemplazar el texto. La -i
bandera alterará el archivo directamente. Elimínelo para una especie de modo "funcionamiento en seco".
Hice mi propia solución antes de encontrar esta pregunta (y respuestas). Busqué diferentes combinaciones de "reemplazar" "varios" y "xml", porque esa era mi aplicación, pero no encontré esta en particular.
Mi problema: tenía archivos xml de primavera con datos para casos de prueba, que contenían objetos complejos. Un refactor en el código fuente de Java cambió muchas clases y no se aplicó a los archivos de datos XML. Para guardar los datos de los casos de prueba, necesitaba cambiar todos los nombres de clase en todos los archivos xml, distribuidos en varios directorios. Todo mientras guardo copias de seguridad de los archivos xml originales (aunque esto no era obligatorio, ya que el control de versiones me salvaría aquí).
Estaba buscando alguna combinación de find
+sed
, porque funcionó para mí en otras situaciones, pero no con varios reemplazos a la vez.
Luego encontré preguntar la respuesta de ubuntu y me ayudó a construir mi línea de comando:
find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
Y funcionó perfectamente (bueno, mi caso tenía seis reemplazos diferentes). Pero tenga en cuenta que tocará todos los archivos * .xml en el directorio actual. Por eso, y si usted es responsable de un sistema de control de versiones, es posible que desee filtrar primero y solo pasar a sed
aquellos que realmente tienen las cadenas que desea; me gusta:
find -name "*.xml" -exec grep -e "firstWord" -e "secondWord" -e "thirdWord" {} \; -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
findstr /spin /c:"quéquieresbuscar" *.xml
será útil.
Realmente cojo, pero no pude hacer que ninguno de los comandos sed funcionara correctamente en OSX, así que hice esta tontería:
:%s/foo/bar/g
:wn
^ - copie estas tres líneas en mi portapapeles (sí, incluya la nueva línea final), luego:
vi *
y mantenga presionado command-v hasta que diga que no quedan archivos.
Tonto ... hacky ... efectivo ...
En una MacBook Pro, utilicé lo siguiente (inspirado en https://stackoverflow.com/a/19457213/6169225 ):
sed -i '' -e 's/<STR_TO_REPLACE>/<REPLACEMENT_STR>/g' *
-i ''
se asegurará de que no realice copias de seguridad.
-e
para expresiones regulares modernas.
-e
solo le dice a sed que el siguiente token es un comando. Para expresiones regulares extendidas, use -E
en su lugar.
El editor de flujo modifica múltiples archivos "in situ" cuando se invoca con el -i
interruptor, lo que toma un archivo de respaldo que termina como argumento. Entonces
sed -i.bak 's/foo/bar/g' *
reemplaza foo
con bar
en todos los archivos en esta carpeta, pero no desciende en subcarpetas. Sin embargo, esto generará un nuevo .bak
archivo para cada archivo en su directorio. Para hacer esto de forma recursiva para todos los archivos en este directorio y todos sus subdirectorios, necesita un ayudante, como find
, para atravesar el árbol de directorios.
find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *
find
le permite más restricciones sobre qué archivos modificar, especificando argumentos adicionales como find ./ -name '*.php' -or -name '*.html' -print0
, si es necesario.
Nota: GNU sed
no requiere un final de archivo, sed -i 's/foo/bar/g' *
también funcionará; FreeBSD sed
exige una extensión, pero permite un espacio intermedio, por lo que sed -i .bak s/foo/bar/g *
funciona.
script para comando multiedit
multiedit [-n PATTERN] OLDSTRING NEWSTRING
A partir de la respuesta de Kaspar, hice un script bash para aceptar argumentos de línea de comando y, opcionalmente, limitar los nombres de archivo que coinciden con un patrón. Ahorre en su $ PATH y haga ejecutable, luego simplemente use el comando anterior.
Aquí está el guión:
#!/bin/bash
_help="\n
Replace OLDSTRING with NEWSTRING recursively starting from current directory\n
multiedit [-n PATTERN] OLDSTRING NEWSTRING\n
[-n PATTERN] option limits to filenames matching PATTERN\n
Note: backslash escape special characters\n
Note: enclose STRINGS with spaces in double quotes\n
Example to limit the edit to python files:\n
multiedit -n \*.py \"OLD STRING\" NEWSTRING\n"
# ensure correct number of arguments, otherwise display help...
if [ $# -lt 2 ] || [ $# -gt 4 ]; then echo -e $_help ; exit ; fi
if [ $1 == "-n" ]; then # if -n option is given:
# replace OLDSTRING with NEWSTRING recursively in files matching PATTERN
find ./ -type f -name "$2" -exec sed -i "s/$3/$4/g" {} \;
else
# replace OLDSTRING with NEWSTRING recursively in all files
find ./ -type f -exec sed -i "s/$1/$2/" {} \;
fi
Si el archivo contiene barras inclinadas invertidas (rutas generalmente), puede intentar algo como esto:
sed -i -- 's,<path1>,<path2>,g' *
ex:
sed -i -- 's,/foo/bar,/new/foo/bar,g' *.sh (in all shell scripts available)
Para mantener mi nodo personal en inglés, escribí un script de utilidad que ayuda a reemplazar varios pares de cadenas viejas / nuevas, para todos los archivos en un directorio de forma recursiva.
Los múltiples pares de cadenas antiguas / nuevas se administran en un mapa hash.
El directorio se puede establecer a través de la línea de comando o la variable de entorno, el mapa está codificado en el script, pero puede modificar el código para cargarlo desde un archivo, si es necesario.
Requiere bash 4.2, debido a alguna nueva característica.
en_standardize.sh:
#! /bin/bash
# (need bash 4.2+,)
#
# Standardize phonetic symbol of English.
#
# format:
# en_standardize.sh [<dir>]
#
# params:
# * dir
# target dir, optional,
# if not specified then use environment variable "$node_dir_en",
# if both not provided, then will not execute,
# *
#
paramCount=$#
# figure target dir,
if [ $paramCount -ge 1 ]; then # dir specified
echo -e "dir specified (in command):\n\t$1\n"
targetDir=$1
elif [[ -v node_dir_en ]]; then # environable set,
echo -e "dir specified (in environment vairable):\n\t$node_dir_en\n"
targetDir=$node_dir_en
else # environable not set,
echo "dir not specified, won't execute"
exit
fi
# check whether dir exists,
if [ -d $targetDir ]; then
cd $targetDir
else
echo -e "invalid dir location:\n\t$targetDir\n"
exit
fi
# initial map,
declare -A itemMap
itemMap=( ["ɪ"]="i" ["ː"]=":" ["ɜ"]="ə" ["ɒ"]="ɔ" ["ʊ"]="u" ["ɛ"]="e")
# print item maps,
echo 'maps:'
for key in "${!itemMap[@]}"; do
echo -e "\t$key\t->\t${itemMap[$key]}"
done
echo -e '\n'
# do replace,
for key in "${!itemMap[@]}"; do
grep -rli "$key" * | xargs -i@ sed -i "s/$key/${itemMap[$key]}/g" @
done
echo -e "\nDone."
exit
Usar el comando ack sería mucho más rápido así:
ack '25 Essex' -l | xargs sed -i 's/The\ fox \jump/abc 321/g'
Además, si tiene un espacio en blanco en el resultado de la búsqueda. Necesitas escapar de eso.
Estoy dando un ejemplo para corregir un error común de shebang en las fuentes de Python.
Puedes probar el enfoque grep / sed. Aquí hay uno que funciona con GNU sed y no romperá un repositorio git:
$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}
O puedes usar greptile :)
$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .
Acabo de probar el primer script, y el segundo debería funcionar también. Tenga cuidado con los caracteres de escape, creo que debería ser más fácil usar greptile en la mayoría de los casos. Por supuesto, puede hacer muchas cosas interesantes con sed, y para eso puede ser preferible dominar su uso con xargs.
Encontré este de otra publicación (no recuerdo cuál) y, aunque no es el más elegante, es simple y, como usuario novato de Linux, no me ha causado problemas
for i in *old_str* ; do mv -v "$i" "${i/\old_str/new_str}" ; done
si tiene espacios u otros caracteres especiales, use un \
for i in *old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
para cadenas en subdirectorios use **
for i in *\*old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
Hay una manera más fácil mediante el uso de un archivo de script simple:
# sudo chmod +x /bin/replace_string_files_present_dir
abra el archivo en gedit o un editor de su elección, yo uso gedit aquí.
# sudo gedit /bin/replace_string_files_present_dir
Luego, en el editor, pegue lo siguiente en el archivo
#!/bin/bash
replace "oldstring" "newstring" -- *
replace "oldstring1" "newstring2" -- *
#add as many lines of replace as there are your strings to be replaced for
#example here i have two sets of strings to replace which are oldstring and
#oldstring1 so I use two replace lines.
Guarde el archivo, cierre gedit , luego salga de su terminal o simplemente ciérrelo y luego inícielo para poder cargar el nuevo script que agregó.
Navegue hasta el directorio donde tiene varios archivos que desea editar. Entonces corre:
#replace_string_files_present_dir
Presione Intro y esto reemplazará automáticamente oldstring y oldstring1 en todos los archivos que los contienen con la cadena de noticias correcta y la cadena de noticias1 respectivamente.
Omitirá todos los directorios y archivos que no contengan las cadenas antiguas.
Esto podría ayudar a eliminar el tedioso trabajo de escribir en caso de que tenga varios directorios con archivos que necesitan reemplazo de cadena. Todo lo que tiene que hacer es navegar a cada uno de esos directorios, luego ejecutar:
#replace_string_files_present_dir
Todo lo que tiene que hacer es asegurarse de haber incluido o agregado todas las cadenas de reemplazo como le mostré anteriormente:
replace "oldstring" "newstring" -- *
al final del archivo / bin / replace_string_files_present_dir .
Para agregar una nueva cadena de reemplazo, simplemente abra el script que creamos escribiendo lo siguiente en el terminal:
sudo gedit /bin/replace_string_files_present_dir
No se preocupe por la cantidad de cadenas de reemplazo que agregue, no tendrán efecto si no se encuentra la cadena antigua .
.gitlab-ci.yml
ao a travis.yml
). Cada vuelta que consiste en escribir un guión para ejecutarlo más tarde es un antipatrón, ya que luego necesitará guiar la creación del guión (y la mayoría de las veces me da problemas)
$ reemplaza "From" "To" - `find / path / to / folder -type f`
(reemplazar - una utilidad de reemplazo de cadenas del sistema de base de datos MySQL)