
Estoy intentando escribir un script que garantice que todos los archivos de texto terminen con un carácter de nueva línea.
Cuando ejecuto este comando en una carpeta en particular:
find . -exec ed -s {} <<< w \;
Obtengo el siguiente resultado:
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Newline appended
Ok, pero ¿a qué archivos se agregaron las nuevas líneas? No puedo ver ningún cambio en el historial de Git, entonces, ¿estos archivos no tienen seguimiento?
También eliminé deliberadamente la nueva línea del final de uno de mis archivos de texto y ed
no la vuelvo a agregar...
Respuesta1
Su comando es ligeramente incorrecto al igual <<<
que una redirección de entrada (aquí-cadena) que está adjunta a find
, no a ed
.
Para ampliar ligeramente su comando:
find . -type f -exec sh -c '
for pathname do
echo w | ed -s "$pathname"
done' sh {} +
Esto solo afectaría a los archivos normales en el directorio actual o en cualquier lugar debajo de él, y no intentaría editar directorios y otros tipos de archivos con ed
. Tenga en cuenta que los archivos binarios también son archivos normales, por lo que debemos asumir que solo los ejecuta en directorios que contienen archivos de texto (para no dañar los ejecutables compilados, archivos de imagen, etc.)
Para lotes de archivos normales, esto llamaría a un breve script de shell en línea. El script recorrería los nombres de ruta que le dieron find
y abriría cada uno de ellos en ed
, solo para guardar el archivo inmediatamente. Esto agrega la nueva línea a los archivos que aún no terminan con un carácter de nueva línea.
Para obtener una pista sobre qué archivos se modifican realmente con esto, imprima el nombre de la ruta antes de llamar ed
. Esto daría como resultadotodoEncontré nombres de rutas, pero la lista se intercalaría con mensajes de "Nueva línea agregada" después de algunos de ellos.
find . -type f -exec sh -c '
for pathname do
printf "%s\n" "$pathname"
echo w | ed -s "$pathname"
done' sh {} +
Para detectar qué archivos fueron realmente modificados por esto, puede escribir en un archivo temporal, compararlo con el archivo original y reemplazar el original con el archivo temporal si hay una diferencia.
find . -type f -exec sh -c '
tmpfile=$(mktemp); trap "rm -f \"$tmpfile\"" EXIT
for pathname do
printf "w %s\n" "$tmpfile" | ed -s "$pathname" 2>/dev/null
if ! cmp -s "$tmpfile" "$pathname"; then
printf "Fixed %s\n" "$pathname"
mv "$tmpfile" "$pathname"
fi
done' sh {} +
Esto tiene el beneficio adicional de que no actualizará las marcas de tiempo en archivos distintos de los que realmente modifica.
Esto también suprime el mensaje "Nueva línea agregada" ed
y, en su lugar, genera un mensaje personalizado cada vez que se modifica un archivo.
Ver también: