¿Cómo eliminar el espacio en blanco final de todos los archivos de forma recursiva?


122

¿Cómo puede eliminar todo el espacio en blanco final 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.


¿Está buscando una solución "portátil" o más específica para el sistema operativo? ¿Qué sistema operativo estás usando?
Joe Pineda

3
Me encantaría ver una versión de esto que funcione en OS X Snow Leopard e ignore las carpetas .git y .svn.
Trevor Turk

Respuestas:


83

Aquí hay una solución OS X> = 10.6 Snow Leopard.

Ignora las carpetas .git y .svn y sus contenidos. Además, no dejará un archivo de copia de seguridad.

export LC_CTYPE=C
export LANG=C
find . -not \( -name .svn -prune -o -name .git -prune \) -type f -print0 | xargs -0 sed -i '' -E "s/[[:space:]]*$//"

10
Puede hacerlo más rápido usando en \+lugar de *en la cadena de reemplazo; de lo contrario, coincide en cada línea.
l0b0

10
Puede usar [[: blank:]] para eliminar pestañas y espacios.
Leif Gruenwoldt

21
En Mountain Lion esto vuelve sed: RE error: illegal byte sequencepara mí.
Bryson

12
Para aquellos de ustedes que tienen problemas con la "secuencia de bytes ilegal": ingrese export LANG=Ce intente nuevamente
Georg Ledermann

3
En OS X 10.9 también necesitaba lo export LC_CTYPE=C que se encuentra aquí: stackoverflow.com/questions/19242275/…
kissgyorgy

31

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 de .gitdirectorio, trate de añadir: -not -iwholename '*.git*'.


37
No intente esto en un repositorio de git, ya que puede dañar el almacenamiento interno de git.
mgold

11
@mgold Demasiado tarde, grrr; /
kenorb

3
Para aclarar, está bien ejecutar esto dentro de una subcarpeta de un repositorio de git, solo que no dentro de ninguna carpeta que contenga repositorios de git como descendientes, es decir, no dentro de ninguna carpeta que tenga .gitdirectorios, sin importar cuán profundamente anidados.
Illya Moskvin el

Combinando esta respuesta con @ deepwell para evitar problemas con git / svnfind . -not \( -name .svn -prune -o -name .git -prune \) -type f -print0 | xargs -0 perl -pi -e 's/ +$//'
William Denniss

1
Probablemente haya una mejor manera, pero me recuperé de destrozar un repositorio de git con esto clonando el repositorio en una carpeta separada y luego haciendo rsync -rv --exclude=.git repo/ repo2/que los cambios locales repotambién estuvieran en el (sin daños) repo2.
MatrixManAtYrService

29

Dos enfoques alternativos que también funcionan con las nuevas líneas de DOS (CR / LF) y hacen un trabajo bastante bueno para evitar archivos binarios :

Solución genérica que comprueba que el tipo MIME comienza 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 de repositorio de Git de Mat que utiliza la-Iopción degit grepomitir archivos que Git considera binarios:

git grep -I --name-only -z -e '' | xargs -0 sed -i 's/[ \t]\+\(\r\?\)$/\1/'

3
Así que realmente me gusta esta solución git. Realmente debería estar en la cima. Sin embargo, no quiero guardar retornos de carro. Pero prefiero esto al que combiné en 2010.
odinho - Velmont

Mi git se queja de que la expresión -e está vacía, pero funciona muy bien usando -e '. *'
muirbot

@okor En GNU, sedla opción de sufijo -ies opcional , pero en BSDsed no lo es. Es estrictamente hablando, no es necesario aquí de todos modos, así que lo eliminaré.
l0b0

24

En Bash:

find dir -type f -exec sed -i 's/ *$//' '{}' ';'

Nota: Si está utilizando .gitrepositorio, trate de añadir: -not -iwholename '.git'.


Esto genera errores como este para cada archivo encontrado. sed: 1: "dir / file.txt": comando a espera \ seguido de texto
iamjwc

Reemplazando ';' con \; Deberia trabajar. (También las citas alrededor de {} no son estrictamente necesarias).
agnul

44
Para eliminar todos los espacios en blanco, no solo los espacios, debe reemplazar el carácter de espacio con [: espacio:] en su expresión regular sed.
WMR

Otra nota al margen: esto solo funciona con versiones sed> = 4, las versiones más pequeñas no admiten la edición en el lugar.
WMR

1
Esto me rompió la
cabeza

14

Esto funcionó para mí en OSX 10.5 Leopard, que no utiliza 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 deben excluirse (lo hice)!

Puede usar -prune para ignorar ciertos directorios o archivos. Para los archivos Python en un repositorio git, puede usar algo como:

find dir -not -path '.git' -iname '*.py'

¿Alguna posibilidad de que puedas aclarar esto? Me gustaría un comando que elimine los espacios en blanco finales de todos los archivos en un directorio de forma recursiva, mientras ignora el directorio ".git". No puedo seguir tu ejemplo ...
Trevor Turk

Si está utilizando tcsh, deberá cambiar las comillas dobles a comillas simples. De lo contrario, obtendrá un "Nombre de variable ilegal". error.
Brandon Fosdick

GNU sed es similar pero haces -i.bak o --in-place = .bak, terminando con un comando completo de find dir -not -path '.git' -iname '*.py' -print0 | xargs -0 sed --in-place=.bak 's/[[:space:]]*$//'. Sustitúyalo dirpor el directorio en cuestión como el nivel superior para recurrir.
David Gardner

sed -i .bak? ¿No debería ser sed -i.bak(sin el espacio)?
Ondra Žižka

9

Ack fue hecho 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 (como ack o ack-grep ).

Es solo un programa Perl, por lo que también está disponible en una versión de un solo archivo que puede descargar y ejecutar. Ver: Instalar Ack


ackes maravilloso. Lo he estado utilizando durante varios años y está disponible en casi todos los repositorios de paquetes para la mayoría de las distribuciones.
Felipe Alvarez

8

ex

Intenta usar Ex editor (parte de Vim):

$ ex +'bufdo!%s/\s\+$//e' -cxa **/*.*

Nota: Para la recursividad (bash4 y zsh), utilizamos una nueva opción de globalización ( **/*.*). Habilitado shopt -s globstar.

Puede agregar la siguiente función en su .bash_profile:

# Strip trailing whitespaces.
# Usage: trim *.*
# See: https://stackoverflow.com/q/10711051/55075
trim() {
  ex +'bufdo!%s/\s\+$//e' -cxa $*
}

sed

Para usar sed, verifique: ¿Cómo eliminar espacios en blanco al final con sed?

find

Busque el siguiente script (por ejemplo remove_trail_spaces.sh) para eliminar espacios en blanco finales de los archivos:

#!/bin/sh
# Script to remove trailing whitespace of all files recursively
# See: /programming/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 recomendado por Spring Framework Code Style .


find . -type f -name "*.java" -exec perl -p -i -e "s/[ \t]$//g" {} \;solo elimina un espacio final en lugar de todos.
Karl Richter

6

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.


Para archivos específicos: buscar. -nombre '* .rb' | xargs -I {} sed -i '' 's / [[: espacio:]] * $ // g' {}
Gautam Rege

No necesita el parámetro '' para sed; o podría estar perdiendo algo. Lo probé en todos los archivos en un directorio dado, así: sed -i 's / [[: space:]] * $ // g' util / *. M
Mircea

6

En lugar de excluir archivos, aquí hay una variación de lo anterior, las listas explícitamente blancas de los archivos, en función de la extensión del archivo, que desea eliminar, no dude en sazonar al gusto:

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:]]*$//"

Para que esto funcionara para mí, necesitaba agregar citas:-name "*.rb*"
haroldcarr

5

Terminé ejecutando esto, que es una mezcla entre pojo y la versión adams.

Limpiará tanto los espacios en blanco finales, como también otra forma de espacios en blanco finales, el retorno de 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, al no permitir tomar archivos con ".git" o ".svn". Pero cuidado, que va a tocar archivos binarios si tienes alguna. Use -iname "*.py" -or -iname "*.php"después -type fsi solo desea que toque, por ejemplo, archivos .py y .php.

Actualización 2 : ahora reemplaza todo tipo de espacios al final de la línea (lo que también significa pestañas)


44
No sé lo que está sucediendo, pero esto borró por completo mi repositorio de git y alteró mis imágenes. ¡GENTE, TENGA MÁS CUIDADO QUE YO!
mattalxndr

Sí, arruinará los archivos binarios. Sin embargo, no debería tocar su repositorio de git en absoluto, ya que omite todo lo que reside dentro de una carpeta .git. Pero tal vez solo si estás en la misma carpeta.
odinho - Velmont

4

Esto funciona bien ... agregar / eliminar --incluye para tipos de archivo específicos:

egrep -rl ' $' --include *.c *  | xargs sed -i 's/\s\+$//g'

4

Rubí:

irb
Dir['lib/**/*.rb'].each{|f| x = File.read(f); File.write(f, x.gsub(/[ \t]+$/,"")) }

3

Yo uso expresiones regulares. 4 pasos:

  1. Abra la carpeta raíz en su editor (yo uso Visual Studio Code).
  2. Toque el icono Buscar a la izquierda y habilite el modo de expresión regular.
  3. Ingrese "+ \ n" en la barra de búsqueda y "\ n" en la barra Reemplazar.
  4. Haga clic en "Reemplazar todo".

Esto elimina todos los espacios finales al final de cada línea en todos los archivos. Y puede excluir algunos archivos que no se ajustan a esta necesidad.


2

1) Muchas otras respuestas usan -E. No estoy seguro de por qué, ya que esa es una opción de compatibilidad BSD no documentada .-rdebería usarse en su lugar.

2) Otras respuestas de uso -i ''. Eso debería ser solo -i(o -i''si se prefiere), porque -itiene el sufijo justo 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 alias git check-whitespaceque enumera los archivos con espacios en blanco al final. El segundo corre sedsobre ellos.

Solo uso en \tlugar de hacerlo, [:space:]ya que normalmente no veo pestañas verticales, formularios de alimentación y espacios no rompibles. Su medida puede variar.


1

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 interesante es que tengo que ejecutar esto 3-4 veces antes de que todos los archivos se arreglen, gsedsiguiendo todas las instrucciones de limpieza .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.