Evite reemplazar espacios al renombrar archivos

10

Estoy tratando de cambiar el nombre de archivos como este:

for file in *;
do
mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')";
done

Pero el sedcomando reemplaza todos los espacios con _.

¿Cómo puedo editar el sedcomando para que incluya espacios junto con los caracteres especificados? He intentado usar \spero no funciona ...

EDITAR:
Por ejemplo: el archivo trip: hilldebe renombrarse: trip_ hillpero el comando anterior lo hace trip__hill.

Zanna
fuente
Estoy moviendo algunos archivos de Linux a Mac. Pero por alguna razón, el sistema Mac no puede leer todos los nombres de archivos, así que estoy tratando de cambiarles el nombre. Agregar un espacio al comando anterior no funciona. Y tiene razón: quiero reemplazar todos los caracteres con '_' excepto los especificados. Y no sé cómo incluir el personaje espacial.
Tenga en cuenta que estoy tratando de reemplazar todos los caracteres con '_' excepto los especificados. No hay un patrón particular para los archivos que se renombran, por lo que no puedo usar este comando perl.

Respuestas:

11

No analice los nombres de archivo con sed! La salida de echo "$file"puede no ser confiable.

Uso rename. En 17.10 necesitas instalarlo primero

sudo apt install rename

Luego:

rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' *

Notas

  • eliminar -ndespués de probar para cambiar el nombre de los archivos
  • -- fin de opciones en caso de que algún archivo comience con -
  • [^-A-Za-z0-9_ .]caracteres que no queremos reemplazar: poner -primero o último para que no pueda indicar un rango (se trata literalmente en estas posiciones).
  • Se pueden incluir espacios en la clase
  • . se trata literalmente (en otros contextos regex significa cualquier carácter y necesita ser escapado).

Esto también funciona en sed:

$ echo 'trip: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g'
trip_ hill

Si agrego un espacio al final en su versión, aparece un error:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g'
sed: -e expression #1, char 22: Invalid range end

Pero con -al final, funciona:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ hill

Entonces, tal vez la posición del guión causó su problema cuando agregó el espacio. ¡Pero el consejo de no analizar nombres de archivos es válido!

Zanna
fuente
Este comando funciona gracias. También ha identificado claramente los errores en el comando que utilicé.
2
Gracias de nuevo. Tenga en cuenta que no es necesario usar la barra diagonal '\' en el caso de usar sed. Porque esto agrega '\' a la lista de caracteres ignorados.
2
@latach Eso es una barra invertida, pero tienes toda la razón. Después de probar y cavar, descubrí que .es literal en una clase de caracteres. TIL!
Zanna
2

También puede usar el shell, la expansión de parámetros de Bash puede hacer sustitución:

for f in ./* ; do
    mv "$f" "${f//[^-A-Za-z0-9._ ]/_}"
done

La doble barra le dice que reemplace todas las coincidencias, aparte de eso, la sintaxis es sencilla.

ilkkachu
fuente