¿Cómo cambio el nombre de los archivos con espacios usando el shell de Linux?

28

Nombré varios archivos con espacios en ellos y quiero reemplazar el espacio con _. Sin embargo, cada vez que escribo un comando en el shell con el nombre del archivo (por ejemplo Spring 2011), el shell no reconoce el archivo o directorio.

¿Qué puedo hacer sobre esto? ¿Hay alguna forma de usar el carácter unicode para un espacio?

Phil Braun
fuente
para cambiar el nombre de los archivos N mediante programación, use un bashbucle for: vea mi solución aquí .
Trevor Boyd Smith

Respuestas:

33

Escapar del espacio, por ejemplo Spring\ 2011, o usar comillas, por ejemplo 'Spring 2011'. En el futuro, generalmente es una mala idea usar nombres de archivo con espacios en ellos en cualquier * NIX.

Si tienes rename, puedes usar esto:

rename ' ' '_' [filenames...]
Rafe Kettler
fuente
1
¿Sabes que hay alguna forma de hacer esto para todos los archivos a la vez?
3
por qué es una mala idea? Es responsabilidad del programador manejar los nombres de archivo correctamente.
Glenn Jackman
1
@rafe, realmente es propenso a errores al no manejar los nombres de archivos correctamente por adelantado El esfuerzo adicional se produce al tener que depurar un script cuando simplemente se olvida de citar variables que contienen un nombre de archivo.
Glenn Jackman
3
Esta respuesta no parece funcionar (en Ubuntu 12.04 LTS, al menos). Sin embargo, la respuesta de unutbu funciona bien.
ADN
1
esto solo hizo el primer espacio para mí ... lo cual no es útil (tengo la renameversión 2.23)
Trevor Boyd Smith
30

Si su máquina tiene el comando de cambio de nombre , esto cambiará todos los espacios a guiones bajos en todos los archivos / directorios en el directorio de trabajo actual:

rename 's/ /_/g' *
unutbu
fuente
Confirmado para trabajar en Ubuntu 12.04
anthonygore
1
no funcionó para mí ... recibí un error de "renombrar: no hay suficientes argumentos". Tengo la versión rename --version rename from util-linux 2.23.2.
Trevor Boyd Smith
24

Si no tiene renameo prefiere usar solo el shell:

for f in *\ *; do mv "$f" "${f// /_}"; done

Desglosado:

  • *\ *selecciona todos los archivos con un espacio en su nombre como entrada para el forbucle.
  • Las comillas "$f"son importantes porque sabemos que hay un espacio en el nombre del archivo y, de lo contrario, aparecería como 2+ argumentos para mv.
  • ${f//str/new_str}es una característica de sustitución de cadena específica de bash. Todas las instancias de strse reemplazan con new_str.
blahdiblah
fuente
2
esto funciona pero para mí solo reemplaza el primer espacio. si lo uso for f in *\ *; do mv "$f" "${f// /_}"; donefunciona
billynoah
@billynoah Buena captura, actualizada.
blahdiblah
@blahdiblah ¡Muchas gracias! ¡Me acabas de salvar tanto tiempo!
Guerrilla
@blahdiblah su solución es mucho más elegante que mi solución . buen trabajo. No pensé que el glob for loop funcionaría ... así que hice el glob fuera del loop for.
Trevor Boyd Smith
3

mv "Spring 2011.file" Spring_2011.file debería decirle a la línea de comandos que tome la cadena entre comillas como una sola entrada.

Rockerest
fuente
Esta es la única respuesta que podría llegar a trabajar.
blakeoft
1

Para cambiar el nombre de los archivos N mediante programación, puede usar un bashbucle for simple .

#!/bin/bash

set -eux

# find all your files by using a `grep` pattern
pattern="insert_filename_pattern_here" # you must enter your filename pattern here

# create an array of filenames and split on newlines
IFS=$'\n'
tmp=($(ls | grep ${pattern}))
unset IFS

# for each filename
for filename in "${tmp[@]}"; do
    # rename the filename to use "_" character instead of a " " character
    mv -v "${filename}" "${filename// /_}"
done

Si tiene menos de 5 nombres de archivo, puede escribir manualmente todos los nombres de archivo y usar el renamecomando como sugiere la solución anterior . Pero para mí ... prefiero la solución programática ... incluso cuando solo hay 4 archivos.

PD

Si no está familiarizado con Bashla expansión de parámetros (es decir ${filename// /_}), puede usar el renamecomando:

if ((0)); then
    mv -v "${filename}" "${filename// /_}"
else
    rename ' ' '_' "${filename}"
fi
Trevor Boyd Smith
fuente