¿Cómo cambiar el nombre de los archivos durante la copia?

12

¿Cómo copiaría (estilo de archivo donde no se cambia la fecha) todos los archivos en un directorio de respaldo al directorio del usuario mientras cambio el nombre de cada archivo para eliminar la porción de cadena aleatoria del nombre (es decir, -2b0fd460_1426b77b1ee_-7b8e)?

cp de:

/backup/path/data/Erp.2014.02.16_16.57.03-2b0fd460_1426b77b1ee_-7b8e.etf

a:

/home/user/data/Erp.2014.02.16_16.57.03.etf

Cada archivo siempre comenzará con "Erp". seguido por la cadena de sello de fecha y hora seguida por la cadena aleatoria y luego la extensión ".etf". Quiero mantener todos los elementos de nombre, incluida la marca de fecha y hora. Solo quiero eliminar la cadena aleatoria.

La cadena aleatoria permite múltiples copias de seguridad del mismo archivo. Sin embargo, en este caso, simplemente ejecuté fdupes y no hay duplicados. Entonces, simplemente puedo restaurar todos los archivos, eliminando la cadena aleatoria.

Estoy buscando un comando bash de una línea para hacerlo.

Si eso no funciona, podría hacerlo en dos o más pasos. Normalmente uso KRename, pero en este caso necesito hacerlo en bash. (Estoy trabajando de forma remota).

MountainX
fuente

Respuestas:

7

paxpuede hacer todo esto a la vez. Podrías hacerlo:

cd /backup/path/data && pax -wrs'/-.*$/.etf/' Erp*etf /home/user/data

paxconserva los tiempos de forma predeterminada, pero puede agregar -pepara preservar todo (mejor hecho como root) o -pppara preservar permisos, por ejemplo:

cd /backup/path/data && pax -wrs'/-.*$/.etf/' -pe Erp*etf /home/user/data

De lo contrario ( paxgeneralmente no está disponible por defecto), seguramente es mejor hacer una copia que a rename:

cp -a /backup/path/data/Erp*.etf /home/user/data
rename 's/-.*$/.etf/' /home/user/data/Erp*.etf

De esta manera, no se inicia un proceso diferente para cada archivo.

Graeme
fuente
1
Puedo ver que necesito familiarizarme pax. Esto parece una herramienta muy útil. Me hace preguntarme por qué no es estándar en más distribuciones ...
MountainX
@MountainX, buena pregunta, según Wikipedia, paxha estado en la base estándar de Linux desde 2005. Además, la alternativa para esto, GNU cpio, es posiblemente la herramienta GNU menos característica que existe.
Graeme
1
+1 para su última solución y de esta manera no se inicia un proceso diferente para cada archivo. Pero rename es diferente en Fedora / Red Hat: no sé cómo usarlo en este caso.
erik
15

Puedes usar el cpcomando con la -aopción

-a, --archive
       same as -dR --preserve=all

Y luego use un bucle for para cambiar el nombre de todos los archivos mientras los copia:

for file in Erp*etf; do
  cp -a $file destinationDirectory/${file%%-*}.etf
done

Listo. Inicie este comando en el directorio de origen.

Explicación: El %%-*cortará todos los caracteres después de la primera aparición de un guión / menos -y .etfal final nuevamente agregará la extensión del archivo.

Bueno, y como un trazador de líneas, póngalo todo en una línea. :-) Me gusta esto

for file in Erp*etf; do cp -a $file destinationDirectory/${file%%-*}.etf; done
erik
fuente
1
Gracias, ¿podría por favor citar la documentación para el %%-*consejo? Soy curioso.
soyuka
3

En zsh, use zmv. Pon esto en tu .zshrc:

autoload -U zmv
alias zcp='zmv -C'
alias zln='zmv -L'

Luego usa

zcp '/backup/path/data/(*)-[0-9A-Fa-f_]#.(*)' '/home/user/data/$1$2'

En bash:

zsh -c 'autoload zmv; zmv -C $0 $1' '/backup/path/data/(*)-[0-9A-Fa-f_]#.(*)' '/home/user/data/$1$2'

Si no tiene zsh, una forma POSIX usa pax (esto copia los directorios de forma recursiva).

Si está en un sistema restringido sin zsh y sin pax, puede usar un bucle:

for source in /backup/path/data/*-*.etf; do
  basename=${source##*/}
  cp "$source" "/home/user/data/${basename%-*}.${basename##*.}"
done
Gilles 'SO- deja de ser malvado'
fuente
1

cpNo tiene esa capacidad. Recuerdo cpiohaber podido hacer eso, pero la página de manual actual dice lo contrario. Sin embargo, (gnu) tartiene una --transformopción:

 --transform, --xform EXPRESSION
       use sed replace EXPRESSION to transform file names

Entonces tendría un cmdline como:

(cd /backup/path/data; tar --create --transform 's/-.*-....//' .) | (cd /home/user/data; tar --extract)
Ricky Beam
fuente