bash - characters - ¿Cómo eliminar los espacios en blanco finales de todos los archivos recursivamente?
trim unix shell (14)
¿Cómo puede eliminar todos los espacios en blanco finales de un proyecto completo? Comenzando en un directorio raíz y eliminando el espacio en blanco final de todos los archivos en todas las carpetas.
Además, quiero poder modificar el archivo directamente y no solo imprimir todo en stdout.
ex
Intenta usar el editor Ex (parte de Vim):
$ ex +''bufdo!%s//s/+$//e'' -cxa **/*.*
Nota: Para la recursividad (bash4 y zsh), usamos una nueva opción globbing ( **/*.*
). Habilitado por shopt -s globstar
.
Puede agregar la siguiente función a su .bash_profile
:
# Strip trailing whitespaces.
# Usage: trim *.*
# See: https://.com/q/10711051/55075
trim() {
ex +''bufdo!%s//s/+$//e'' -cxa $*
}
sed
Para usar sed
, compruebe: ¿Cómo eliminar los espacios blancos finales con sed?
find
Busque la siguiente secuencia de comandos (por ejemplo, remove_trail_spaces.sh
) para eliminar los espacios en blanco finales de los archivos:
#!/bin/sh
# Script to remove trailing whitespace of all files recursively
# See: https://.com/questions/149057/how-to-remove-trailing-whitespace-of-all-files-recursively
case "$OSTYPE" in
darwin*) # OSX 10.5 Leopard, which does not use GNU sed or xargs.
find . -type f -not -iwholename ''*.git*'' -print0 | xargs -0 sed -i .bak -E "s/[[:space:]]*$//"
find . -type f -name /*.bak -print0 | xargs -0 rm -v
;;
*)
find . -type f -not -iwholename ''*.git*'' -print0 | xargs -0 perl -pi -e ''s/ +$//''
esac
Ejecute este script desde el directorio que desea escanear. En OSX al final, eliminará todos los archivos que terminan en .bak
.
O solo:
find . -type f -name "*.java" -exec perl -p -i -e "s/[ /t]$//g" {} /;
que es la forma recomendada por Spring Framework Code Style .
1) Muchas otras respuestas usan -E
. No estoy seguro de por qué, ya que esa es la opción de compatibilidad BSD no documentada . -r
debe usar en su lugar.
2) Otras respuestas usan -i ''''
. Eso debería ser solo -i
(o -i''''
si se prefiere), porque -i
tiene el sufijo inmediatamente después.
3) Solución específica de Git:
git config --global alias.check-whitespace /
''git diff-tree --check $(git hash-object -t tree /dev/null) HEAD''
git check-whitespace | grep trailing | cut -d: -f1 | uniq -u -z | xargs -0 sed --in-place -e ''s/[ /t]+$//''
El primero registra un git alias check-whitespace
que enumera los archivos con espacios en blanco al final. El segundo corre sed
sobre ellos.
Solo uso /t
lugar de [:space:]
ya que normalmente no veo las pestañas verticales, las alimentaciones de formularios ni los espacios no rompibles. Su medida puede variar.
Ack fue creado para este tipo de tarea.
Funciona igual que grep, pero sabe que no debe descender a lugares como .svn, .git, .cvs, etc.
ack --print0 -l ''[ /t]+$'' | xargs -0 -n1 perl -pi -e ''s/[ /t]+$//''
Mucho más fácil que saltar a través de aros con find / grep.
Ack está disponible a través de la mayoría de los administradores de paquetes (ya sea como ack o ack-grep ).
Es solo un programa Perl, por lo que también está disponible en una versión de archivo único que puede descargar y ejecutar. Ver: Ack Instalar
Aquí hay una solución OS X> = 10.6 Snow Leopard.
Ignora las carpetas .git y .svn y sus contenidos. Tampoco dejará un archivo de respaldo.
find . -not /( -name .svn -prune -o -name .git -prune /) -type f -print0 | xargs -0 sed -i '''' -E "s/[[:space:]]*$//"
Dos enfoques alternativos que también funcionan con líneas nuevas de DOS (CR / LF) y hacen un buen trabajo para evitar archivos binarios :
Solución genérica que verifica que el tipo MIME comience con text/
:
while IFS= read -r -d '''' -u 9
do
if [[ "$(file -bs --mime-type -- "$REPLY")" = text/* ]]
then
sed -i ''s/[ /t]/+/(/r/?/)$//1/'' -- "$REPLY"
else
echo "Skipping $REPLY" >&2
fi
done 9< <(find . -type f -print0)
Solución específica del repositorio de Git por Mat que usa la opción -I
de git grep
para omitir archivos que Git considera binarios:
git grep -I --name-only -z -e '''' | xargs -0 sed -i ''s/[ /t]/+/(/r/?/)$//1/''
En Bash:
find dir -type f -exec sed -i ''s/ *$//'' ''{}'' '';''
Nota: Si está utilizando .git
repositorio .git
, intente agregar: -not -iwholename ''.git''
.
En lugar de excluir archivos, aquí hay una variación de las listas explícitamente blancas de los archivos, basados en la extensión de archivo, que desea quitar, siéntase libre de condimentar:
find . /( -name *.rb -or -name *.html -or -name *.js -or -name *.coffee -or /
-name *.css -or -name *.scss -or -name *.erb -or -name *.yml -or -name *.ru /) /
-print0 | xargs -0 sed -i '''' -E "s/[[:space:]]*$//"
Esto es lo que funciona para mí (Mac OS X 10.8, GNU sed instalado por Homebrew):
find . -path ./vendor -prune -o /
/( -name ''*.java'' -o -name ''*.xml'' -o -name ''*.css'' /) /
-exec gsed -i -E ''s//t/ /'' /{} /; /
-exec gsed -i -E ''s/[[:space:]]*$//'' /{} /; /
-exec gsed -i -E ''s//r/n//n/'' /{} /;
Se eliminaron los espacios finales, reemplaza las pestañas con espacios, reemplaza Windows CRLF con Unix /n
.
Lo que es interesante es que tengo que ejecutar esto 3-4 veces antes de que se arreglen todos los archivos, por todas las instrucciones de limpieza.
Esto funcionó para mí en OSX 10.5 Leopard, que no usa GNU sed o xargs.
find dir -type f -print0 | xargs -0 sed -i.bak -E "s/[[:space:]]*$//"
Solo tenga cuidado con esto si tiene archivos que necesitan ser excluidos (¡lo hice)!
Puede usar -prune para ignorar ciertos directorios o archivos. Para archivos Python en un repositorio de git, podrías usar algo como:
find dir -not -path ''.git'' -iname ''*.py''
Esto funciona bien .. add / remove - include para tipos de archivos específicos:
egrep -rl '' $'' --include *.c * | xargs sed -i ''s//s/+$//g''
Rubí:
irb
Dir[''lib/**/*.rb''].each{|f| x = File.read(f); File.write(f, x.gsub(/[ /t]+$/,"")) }
Terminé ejecutando esto, que es una mezcla entre la versión de pojo y adams.
Limpiará tanto el espacio en blanco al final como también otra forma de espacio en blanco al final, el retorno del carro:
find . -not /( -name .svn -prune -o -name .git -prune /) -type f /
-exec sed -i ''s/[:space:]+$//'' /{} /; /
-exec sed -i ''s//r/n$//n/'' /{} /;
No tocará la carpeta .git si hay una.
Editar : lo hizo un poco más seguro después del comentario, no permitiendo tomar archivos con ".git" o ".svn" en él. Pero ten cuidado, tocará archivos binarios si tienes algunos. Use -iname "*.py" -or -iname "*.php"
after -type f
si solo desea que toque, por ejemplo, .py y .php-files.
Actualización 2 : ahora reemplaza todo tipo de espacios al final de la línea (lo que significa también pestañas)
Terminé no usando find y no creando archivos de respaldo.
sed -i '''' ''s/[[:space:]]*$//g'' **/*.*
Dependiendo de la profundidad del árbol de archivos, esta (versión más corta) puede ser suficiente para sus necesidades.
NOTA: esto también toma archivos binarios, por ejemplo.
Utilizar:
find . -type f -print0 | xargs -0 perl -pi.bak -e ''s/ +$//''
si no desea que se generen los archivos ".bak":
find . -type f -print0 | xargs -0 perl -pi -e ''s/ +$//''
como usuario de zsh, puede omitir la llamada para buscar y, en su lugar, usar:
perl -pi -e ''s/ +$//'' **/*
Nota: Para evitar la destrucción del directorio .git
, intente agregar: -not -iwholename ''*.git*''
.