Comando cp, copiar sin sobreescribir -solucionado-

Temas sobre programación ( php, c, sql, html, perl, python, ruby, java, bash, etc ) y recursos ( herramientas, frameworks, hosting, cms, etc )

Moderadores: akodo, maiku

Avatar de Usuario
EnriqueK
Forista Medio
Forista Medio
Mensajes: 367
Registrado: Dom Sep 16, 2007 7:00 am

Comando cp, copiar sin sobreescribir -solucionado-

Mensaje por EnriqueK » Vie Abr 13, 2012 5:24 am

Es común que se repitan nombres de archivos, especialmente los creados por uno, esto trae el problema de que cuando por ejemplo se quiere copiar archivos ubicados en diferente carpetas, esta operación no es del todo correcta ya que los archivos con nombres repetidos no se copian o se sobreescriben, en definitiva quisiera saber si es posible que exista la manera de que a los archivos de nombres repetidos se le agregue un nombre adicional , por ejemplo poniendole (1), (2), etc , o al menos que genere un log para poder tomar acciones en forma manual.
El comando que uso es para hacer un respaldo en /media/F/aaa de todos los archivos .pdf ubicados en una partición que tiene a E por etiqueta, aclarado esto, el comando es el siguiente

find /media/E -iname "*.pdf" -exec cp -u '{}' /media/F/aaa/ \;

Tal vez se pueda usando el comando rsync en vez de cp ya que tiene mayores y mejores opciones
Última edición por EnriqueK el Sab Abr 14, 2012 5:30 am, editado 1 vez en total.
fpuga
Forista Mayor
Forista Mayor
Mensajes: 798
Registrado: Sab Ago 25, 2007 7:00 am
Ubicación: Galicia - España
Contactar:

Re: Comando cp, copiar sin sobreescribir

Mensaje por fpuga » Vie Abr 13, 2012 3:41 pm

No lo he probado pero la idea sería hacer un script del tipo.

Código: Seleccionar todo

# to handle files with whitespaces
IFS='
'

for file in 'find /media/E -iname '*.pdf' ; do

    if [ -f "$file" ] ; then
        echo "file: $file already exists"
    else
        cp "$file" /media/F/aaa/
    fi

done
Mi blog: [url=http://conocimientoabierto.es]Conocimiento Abierto[/url]
Avatar de Usuario
mcun
Administrador
Administrador
Mensajes: 3888
Registrado: Lun Abr 19, 2010 12:30 am
Ubicación: En una de las nalgas del culo del mundo (según la Bersuit Vergarabat)
Contactar:

Re: Comando cp, copiar sin sobreescribir

Mensaje por mcun » Vie Abr 13, 2012 4:09 pm

podrías renombrar los ficheros agregándole la fecha y los segundos, luego hacer un alias con e comando y listo

Código: Seleccionar todo

`date +%F-%N`
PD: lo muevo a programación
Los programadores de verdad no documentan. La documentación es para los idiotas que no pueden leer un volcado de memoria.

Trusted Network and Developer | Lee el Reglamento !! |WIKI-EL | Twitter @mr_mcun
Debian + TTY | ArchLinux + awesome | openSUSE + Gnome-Shell | Linux User #508809
Avatar de Usuario
EnriqueK
Forista Medio
Forista Medio
Mensajes: 367
Registrado: Dom Sep 16, 2007 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por EnriqueK » Vie Abr 13, 2012 7:27 pm

No se, debe de haber una forma mas simple y directa, además como estos archivos son por lo general muy pocos, me conformaría con que se genere un log para poder ubicarlos manualmente, en mi caso, el total de archivos a copiar es de 2713 , pero los que realmente lo hacen son 2686
Avatar de Usuario
neurus
Forista Legendario
Forista Legendario
Mensajes: 1808
Registrado: Dom Oct 10, 2004 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por neurus » Vie Abr 13, 2012 8:33 pm

La idea de fpuga me parece la correcta (aunque no probé el script).

Ahora, armar un log es lo más fácil de Bash:

cp -uv *pdf test/|tee >~/copiados.log

¿Y luego qué harías? Digo, para chequearlo manualmente. Se me ocurre un ls *pdf > archivos.log en el directorio origen, y luego un diff archivos.log copiados.log, para saber cuáles no se han copiado. De todos modos, no le veo la gracia a hacer todo esto manualmente cuando se puede hacer con un script.

Pero si no te molesta hacer el trabajo que le corresponde a la computadora, simplemente utiliza el parámetro -i, y te preguntará cada vez que haya un archivo repetido.

Así es como lo haría yo:

Código: Seleccionar todo

#!/bin/bash
IFS=$'\x0A'$'\x0D'
read -p "Directorio origen: " ORIGEN
read -p "Extension: " EXT
read -p "Directorio destino: " DEST
for i in `find $ORIGEN -name "*.$EXT"` ; do

    if [ -f $DEST/$i ] ; then
        echo "renombrando $i"
	cp $i $DEST/`basename $i .pdf`_copia_$(date|awk '{print $4}'|sed 's/://g').pdf 
    else
        cp $i $DEST
    fi
done
De paso, si alguien me recuerda cómo demonios se usaba date para que imprima la hora con el formato 010203, así no hago esa ridiculez con awk y sed, se lo agradecería.
Avatar de Usuario
EnriqueK
Forista Medio
Forista Medio
Mensajes: 367
Registrado: Dom Sep 16, 2007 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por EnriqueK » Vie Abr 13, 2012 8:54 pm

Claro, el tema es despejar cuales son exactamente los archivos que no se pudieron copiar ya sea por ser repetidos o por que sobreescribieron archivos con el mismo nombre, por eso al menos el de crear un log, pero filtrado para que solo muestre los archivos en conflictos para que se pueda solucionar aunque sea en forma manual.

Por todo esto, es que al no encontrar una solución usando el comando cp, es que trato de hallar respuesta con rsync ya que cuenta con muchas mas opciones.
Por otra parte, si uso el comando cp -a me da una salida en terminal indicando que tales archivos no se copiaron por ser idénticos a otros ya copiados antes, al parecer hace un md5sun en estos casos, pero no fueron todos los archivos, eso quiere decir que el resto simplemente son archivos diferentes con el mismo nombre y solo uno puede ser copiado a menos que se pudiera cambiarles el nombre a estos o que por último me genere un log depurado para ubicar manualmente a estos archivos, cambiarles el nombres y ponerlos en la carpeta de respaldo.
Avatar de Usuario
neurus
Forista Legendario
Forista Legendario
Mensajes: 1808
Registrado: Dom Oct 10, 2004 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por neurus » Vie Abr 13, 2012 9:05 pm

¿Pero miraste el script que te pasé arriba, al menos?

Por otra parte, la opción -b (backup) de rsync renombra los archivos preexistentes en el directorio destino.
Avatar de Usuario
EnriqueK
Forista Medio
Forista Medio
Mensajes: 367
Registrado: Dom Sep 16, 2007 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por EnriqueK » Vie Abr 13, 2012 9:32 pm

No había visto el Script, parece que lo has puesto en otro momento , de todas maneras es algo que me supera y tendría que estudiarlo, por el momento me salta la duda de que si has contemplado el hecho de que por lo general estos archivos tienen nombres de varias palabras, es por eso que en primera instancia preparé el siguiente script, pero ne topé con el problema de los nombres repetidos.

#!/bin/bash
origen="/media/E
destino="/media/F/aaa"
encontrados=""
copiados=""
[ -f ~/lista-pdf.txt ] && rm ~/lista-pdf.txt
cd ~/
echo "buscando archivos, por favor espere ..."
find $origen -iname "*.pdf" > ~/lista-pdf.txt
encontrados=$(cat ~/lista-pdf.txt | wc -l)
echo "copiando archivos, por favor espere ..."
while read line; do
cp "$line" $destino
done < ~/lista-pdf.txt
copiados=$(ls -1 $destino | wc -l)
echo "archivos PDF encontrados:" $encontrados
echo "archivos PDF copiados:" $copiados

L a variable $line está entre comillas para solucionar el tema de los nombres de varias palabras.
Al ejecutar este script es uando me indica la discrepancia entre archivos listado y los copiados.
Avatar de Usuario
neurus
Forista Legendario
Forista Legendario
Mensajes: 1808
Registrado: Dom Oct 10, 2004 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por neurus » Vie Abr 13, 2012 9:41 pm

Para evitar problemas con nombres con espacios, está esto: IFS=$'\x0A'$'\x0D'. Las comillas no sirven de mucho cuando quieres usar un bucle for.

Y tu script no resuelve el problema. Sólo lo informa para que lo resuelvas tu. Eso es lo que no entiendo: qué gracia tiene utilizar un autómata, para ser uno quien acabe haciendo el trabajo automatizado.

Y si además quieres un log de los archivos renombrados, basta con reemplazar echo "renombrando $i" por echo "renombrando $i">> renombrados.log
Avatar de Usuario
EnriqueK
Forista Medio
Forista Medio
Mensajes: 367
Registrado: Dom Sep 16, 2007 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por EnriqueK » Vie Abr 13, 2012 10:51 pm

Gracias Neurus, pero al ejecutar tu script me da exactamente el mismo resultado, o sea el mismo número de archivos copiados que usando la expresión que puse al iniciar el thread.
Al principio lo ejecuta? tal como está, el resultado fue que se copiaron menos archivos, revisando el script , veo que usaste name en vez de iname , corregido esto, el resultado es el indicado al comienzo.
También probé usar rsync -u y seguidamente rsync -ub , el mismo resultado.
Avatar de Usuario
neurus
Forista Legendario
Forista Legendario
Mensajes: 1808
Registrado: Dom Oct 10, 2004 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por neurus » Vie Abr 13, 2012 11:15 pm

Pero entonces debes aclarar(te) lo que quieres hacer.

Lo que hace el script: busca los archivos con la extensión indicada a partir del directorio indicado. Chequea recursivamente si esos nombres existen en el directorio destino.
Si existe: copia el archivo renombrándolo como archivo_copia_date.extensión.
Si no existe: lo copia sin más.

Lo que hace rsync -b: chequea si el nombre del archivo existe en el directorio destino.
Si existe, renombra el archivo original del directorio destino con un .bak, y copia el archivo origen.
Si no existe, copia sin más.

Ambos comportamientos son compatibles con el mensaje que un tal EnriqueK posteó al comienzo del trhead:
quisiera saber si es posible que exista la manera de que a los archivos de nombres repetidos se le agregue un nombre adicional , por ejemplo poniendole (1), (2)
Concretamente: ¿qué quieres hacer?

Y mira, para probarlo, con el script de arriba:

Creo algunos archivos con extensión pdf:

Código: Seleccionar todo

for i in `seq 1 10`; do touch $i.pdf; done

Código: Seleccionar todo

ls *pdf
10.pdf  1.pdf  2.pdf  3.pdf  4.pdf  5.pdf  6.pdf  7.pdf  8.pdf  9.pdf
Es decir, que tengo 10 archivos pdf.
Creo el directorio backup y ejecuto el script. Directorio origen: . ; extensión: pdf; directoriio destino: backup.

Código: Seleccionar todo

ls backup/
10.pdf  1.pdf  2.pdf  3.pdf  4.pdf  5.pdf  6.pdf  7.pdf  8.pdf  9.pdf
Ahora el directorio backup tiene los mismos archivos que el directorio origen.

Agrego algunos archivos en el directorio origen:

Código: Seleccionar todo

for i in `seq 11 20`; do touch $i.pdf; done

Código: Seleccionar todo

ls *pdf
10.pdf  12.pdf  14.pdf  16.pdf  18.pdf  1.pdf   2.pdf  4.pdf  6.pdf  8.pdf
11.pdf  13.pdf  15.pdf  17.pdf  19.pdf  20.pdf  3.pdf  5.pdf  7.pdf  9.pdf
Vuelvo a ejecutar el script, de la misma forma, y vemos qué hay en backup:

Código: Seleccionar todo

ls backup/
10_copia_162826.pdf  17.pdf              3_copia_162825.pdf  7_copia_162826.pdf
10.pdf               18.pdf              3.pdf               7.pdf
11.pdf               19.pdf              4_copia_162826.pdf  8_copia_162826.pdf
12.pdf               1_copia_162825.pdf  4.pdf               8.pdf
13.pdf               1.pdf               5_copia_162826.pdf  9_copia_162826.pdf
14.pdf               20.pdf              5.pdf               9.pdf
15.pdf               2_copia_162825.pdf  6_copia_162826.pdf
16.pdf               2.pdf               6.pdf
Que fue lo que preguntaste al comienzo.
Avatar de Usuario
EnriqueK
Forista Medio
Forista Medio
Mensajes: 367
Registrado: Dom Sep 16, 2007 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por EnriqueK » Vie Abr 13, 2012 11:59 pm

Neurus, lo que quiero es copiar a un DD externo todos los archivos .pdf , PDF .Pdf. y el resto de las combinaciones de mayúscula y mínúsculas de esa extensión , todas las siguienes expresiones me dan el mismo resultado , o sea 2689 archivos copiados
1.- find /media/E -iname "*.pdf" -exec cp -u '{}' /media/F/aaa/ \;
2.- find /media/E -iname "*.pdf" -exec rsync '{}' /media/F/aaa/ \;
3.- find /media/E -iname "*.pdf" -exec rsync -b '{}' /media/F/aaa/ \;
4.- find /media/E -iname "*.pdf" -exec rsync -ub '{}' /media/F/aaa/ \;

El mismo resultado dio al ejecutar tu script
El caso es que el número total de archivos es de 2713, lo que implica que hay archivos con nombres repetidos, pudiendo ser o no archivos idénticos o simplemente tienen el mismo nombre
Avatar de Usuario
neurus
Forista Legendario
Forista Legendario
Mensajes: 1808
Registrado: Dom Oct 10, 2004 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por neurus » Sab Abr 14, 2012 12:12 am

¡Pero entonces el problema no es la copia, sino la búsqueda!

Por qué no pruebas antes qué resultado te da esto:

Código: Seleccionar todo

find /media/E -iname "*.pdf">> lista.txt && cat lista.txt|wc -l
Avatar de Usuario
EnriqueK
Forista Medio
Forista Medio
Mensajes: 367
Registrado: Dom Sep 16, 2007 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por EnriqueK » Sab Abr 14, 2012 12:18 am

enrique@aaaaaaa:~$ find /media/E -iname "*.pdf">> lista.txt && cat lista.txt|wc -l
2713
Avatar de Usuario
neurus
Forista Legendario
Forista Legendario
Mensajes: 1808
Registrado: Dom Oct 10, 2004 7:00 am

Re: Comando cp, copiar sin sobreescribir

Mensaje por neurus » Sab Abr 14, 2012 3:05 am

jajaja

Es imposible. Acá hay algo absurdo. Tanto con el script como con rsync tiene que copiarte todos los archivos. De hecho, eso hace. De eso estoy absolutamente seguro.

A ver, una última prueba, para saber qué demonios está pasando. Es el mismo script, pero con un log detallado:

Código: Seleccionar todo

#!/bin/bash -verbose	
{
    set -x
    
    
IFS=$'\x0A'$'\x0D'
read -p "Directorio origen: " ORIGEN
read -p "Extension: " EXT
read -p "Directorio destino: " DEST
for i in `find $ORIGEN -iname "*.$EXT"` ; do

    if [ -e $DEST/$i ] ; then
        echo "renombrando $i"
	cp $i $DEST/`basename $i .pdf`_copia_$(date|awk '{print $4}'|sed 's/://g').pdf && echo "copiado $i" >> registro.log
    else
        cp $i $DEST && echo "copiado $i" >> registro.log
    fi
done

 set +x
} > registro.log 2>&1
Ten en cuenta que:

1) no verás lo que te está pidiendo, por lo cual deberás escribir el directorio origan [enter], extensión [enter], directorio destino [enter] y se pondrá a trabajar. Esto puede arreglarse, pero ni siquiera creo que valga la pena.

2) el archivo registro.log se guardará en el directorio en que estés ejecutando el script. Supongo que sabes cambiar eso en caso de querer hacerlo.

Una vez terminado, abócate a leer qué pasó, para saber qué archivos no copió y por qué.

PD: si es muy incómodo de leer el registro así como está, puedes quitarle el -verbose a bash, en el encabezado.

######################################

Bueno, finalmente lo entendí.

Pero debo decirlo: te explicas como alguien que equivocó su medicación.

El malentendido tiene origen en que este tipo de problemas surgen cuando el directorio destino contiene archivos que podrían ser sobreescritos por los archivos a copiar. Lo que todos los usuarios que participamos del hilo intentábamos resolver, era ese problema. No fue hasta que te pedí que hicieras la prueba con find que finalmente, y casi de casualidad, hiciste notar que los archivos repetidos están en el origen. No estaba tan lejos mi respuesta: el problema, si bien no es la búsqueda, es el resultado de la búsqueda.

Y el problema con el script es que chequea mal la variable.

Ahí va, el mismo script del comienzo.

Código: Seleccionar todo

#!/bin/bash
  
IFS=$'\x0A'$'\x0D'

ORIGEN=$1
EXT=$2
DEST=$3
for i in `find $ORIGEN -iname "*.$EXT"`; do

    if [ -f $DEST/`basename $i` ] ; then
        echo "renombrando $i"
	cp $i $DEST/`basename $i .pdf`_copia_$(date|awk '{print $4}'|sed 's/://g').pdf && echo "copiado $i"  >> registro.log 
    else
        cp $i $DEST && echo "copiado $i" >> registro.log 
    fi
done
1) Corregida la condición: if [ -f $DEST/`basename $i` ]
2) De paso, un poco más limpio y ágil, con parámetros en lugar de hacerlo interactivo. Uso: script origen extension destino.
Responder
  • Similar Topics
    Respuestas
    Vistas
    Último mensaje