[Bash] Script de copia-backup archivos nuevos

Iniciado por sclub, 19 Diciembre 2010, 21:38 PM

0 Miembros y 1 Visitante están viendo este tema.

sclub

holaaa!!

aver, estoy intentando hacer un script que me sincronize dos unidades, una que me lllevo d'aquí p'allá, y la otra que la tengo en casa siempre.
El codigo es este:
Código (bash) [Seleccionar]

#!/bin/bash

copiaRecurs() {
src="$1"
dst="$2"
for file in $(ls $src)
do
if [ -d "$src/$file" ]; then
if [ ! -e "$dst/$file" ]; then
mkdir "$dst/$file"
fi
`copiaRecurs "$src/$file" "$dst/$file"`
else
if [ "$src/$file" -nt "$dst/$file" ]; then
cp "$src/$file" "$dst/$file"
fi
fi
done
}

pathB="/media/BOX"
pathS="/media/STORE"

boxSof="Softw"
strSof="Software"
boxDoc="Doc"
strDoc="Documentacio"
boxImg="Images"
strImg="Images"

if [ ! -d $pathB ]; then
echo "BOX isn't ready!"
exit
else
if [ ! -d $pathS ]; then
echo "STORE isn't ready!"
exit
fi
fi

copiaRecurs "$pathB/$boxImg" "$pathS/prova"

echo "Cool!!"


El problema que estoy teniendo es que no me copia todo... alguna carpeta me la deja vacia. Aparte mientras se esta copiando saltan algunos 'errores' como estos:
./scripts/syncro.sh: line 12: `/media/BOX/Images/Amsterdam\'08/Peke/DSC06339.JPG': No such file or directory
./scripts/syncro.sh: line 12: `/media/BOX/Images/BBQ(Sept\'09)/DSC00824.JPG': No such file or directory
./scripts/syncro.sh: line 12: `/media/BOX/Images/ClasseESI/Thumbs.db': No such file or directory
./scripts/syncro.sh: line 12: `/media/BOX/Images/Dublin\'09/Adventures/DSC02777.JPG': No such file or directory


Pero esos archivos SÍ existen, es más, me los copia al destino... nose... la cosa es que de una carpeta de 10gb de fotos, 1gb no se ha copiado... y solo tengo localizada una carpeta vacia... el resto deben ser fotos sueltas...
Alguien ve algo raro en el codigo¿??? Estoy empezando a hacerme mis scripts y me lio un poco.

Por otro lado, eso no es lo mismo que un cp -r verdad?? el cp -r sobreescribiria en cualquier caso, sea nuevo o no... correcto??

Bueno, gracias por leer!!

Saludos!

EDIT ---
Cambio el titulo porque al final no he usado recursividad. Código al final.
... because making UNIX friendly is easier than debugging Windows.

leogtz

¿qué es lo que quieres hacer con ese script?

Lo digo para ver si hallamos otra alternativa.
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

sclub

Pues lo que quiero es que yo le de al script, y me copie todos los archivos de BOX a STORE(son 2 HDD's).

Basicamente copia todo a otro HDD, pero solo si su igual en el destino no existe o es mas viejo. Porque sino seria mucho procesador gastado en vano... almomejor yo hay dias que solo he modificado 2 archivos de todo lo que quiero que se copie, pues solo se copiaran esos 2, no todo...

se te ocurre alguna manera mejor¿??? Se me ocurrio que el cp podria tener una opció que compruebe eso(-nt, -ot), pero no la encontré en el man... se me pasó o no la hay¿?

Saludos!!
... because making UNIX friendly is easier than debugging Windows.

leogtz

A mi se me ocurre usar find con sus test's, find trabaja de manera rápida.

Código (bash) [Seleccionar]
TESTS
      Some tests, for example -newerXY and -samefile, allow comparison between the file currently being examined and some reference file specified on  the  command  line.
      When  these  tests are used, the interpretation of the reference file is determined by the options -H, -L and -P and any previous -follow, but the reference file is
      only examined once, at the time the command line is parsed.  If the reference file cannot be examined (for example, the stat(2) system call fails for it), an  error
      message is issued, and find exits with a nonzero status.

      Numeric arguments can be specified as

      +n     for greater than n,

      -n     for less than n,

      n      for exactly n.

      -amin n
             File was last accessed n minutes ago.

      -anewer file
             File  was last accessed more recently than file was modified.  If file is a symbolic link and the -H option or the -L option is in effect, the access time of
             the file it points to is always used.

      -atime n
             File was last accessed n*24 hours ago.  When find figures out how many 24-hour periods ago the file was last accessed, any fractional part is ignored, so  to
             match -atime +1, a file has to have been accessed at least two days ago.

      -cmin n
             File's status was last changed n minutes ago.

      -cnewer file
             File's status was last changed more recently than file was modified.  If file is a symbolic link and the -H option or the -L option is in effect, the status-
             change time of the file it points to is always used.

      -ctime n
             File's status was last changed n*24 hours ago.  See the comments for -atime to understand how rounding affects  the  interpretation  of  file  status  change
             times.

      -empty File is empty and is either a regular file or a directory.


find combinado con -exec, investigalo bien, seguro que te ayuda.

http://content.hccfl.edu/pollock/unix/findcmd.htm
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

sclub

Código (bash) [Seleccionar]

#!/bin/bash

IFS=$'\x0A'$'\x0D'

copiaRecurs() {
srcFolder="$1"
dstFolder="$2"

cd $srcFolder

for srcFile in $(find .)
do

dstFile="$dstFolder/$srcFile"
if [ -d "$srcFile" ]; then
if [ ! -e "$dstFile" ]; then
mkdir "$dstFile"
fi
else
if [ ! -e "$dstFile" ]; then
cp "$srcFile" "$dstFile"
else
#find "$srcFile" -cnewer "$dstFile" -exec sh -c 'exec cp -f "$@" $dstFile' find-copy {} +
if [ "$srcFile" -nt "$dstFile" ]; then
cp -f "$srcFile" "$dstFile"
fi
fi
fi
done
}

pathB="/media/BOX"
pathS="/media/STORE"

copiaRecurs "$pathB/prova" "$pathS/prova"


Me ha venido bien el find! ;) el problema fue que los espacios me los detectaba como un salto de linea y me daba error... al final encontre que si canviaba los caracteres que se imprimian con el espacio(IFS) podia poner unos que son tratados correctamente. :)

Pero segui teniendo un problema... no me actualizaba los archivos. Copiaba lo que no existia, pero si ya existia otro paquete más viejo... me daba error.
Citar# ./syncro.sh
cp: missing destination file operand after `./jkuadgs'
Try `cp --help' for more information.
Eso con el find... supongo que porque no lo se usar correctamente.

Entonces simplemente decicdi comprobarlo con un if y copiar manualmente. Y ya parece que va bien!

Le ves algún inconveniente a este metodo?? o ves algún fallo con la linea del find??

Saludos y gracias!!
... because making UNIX friendly is easier than debugging Windows.

leogtz

La sintaxis sería:

find OPCIONES -exec cp -f {} DESTINO \;

Te dejo un ejemplo:


Código (bash) [Seleccionar]
leo@leo-desktop:~/Escritorio$ find . -type f -iname "vocabulario.txt" -exec cp -vf {} /home/leo/ \;
«./vocabulario.txt» -> «/home/leo/vocabulario.txt»
leo@leo-desktop:~/Escritorio$


{} Hace referencia al archivo en cuestión.
/home/leo/ sería el destino.

\; Necesario para terminar el find.
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

sclub

#6
Perfecto!!! ;-) Ya funciona!

El problema es que no sabia como se usaba el -exec y no encontre una explicación clara con buenos ejemplos que reflejaran mi caso. Pero ahora ya está!! Muchas gracias!!! ;)

Aunque sigo teniendo una duda, las rutas con las que trabajo son así:
Citar/media/BOX/./Images/
y queria sustituirlo por:
Citar/media/BOX/Images/

así que probe con esto:
Código (bash) [Seleccionar]
dstFile=$(sed 's/"./"/"$dstFolder"/' "$srcFile")
y con esto:
Código (bash) [Seleccionar]
dstFile=$(echo "$srcFile" | sed -e 's/"./"/"$dstFolder"/')
con este error:
Citarsed: -e expression #1, char 8: unknown option to `s'

o así:
Código (bash) [Seleccionar]
dstFile=$(echo "$srcFile" | sed -e 's/".\/"/"$dstFolder"/')
sin ningún error, pero sin resultado.

Imagino como no, que el problema será la sintaxis... aver si lo arreglo.
De todas formas, muchas gracias por la ayuda!! Qué de mi sin tí.... xDD

Saludos!!
... because making UNIX friendly is easier than debugging Windows.

leogtz

Pon el código completo, por favor, para que otros vean cómo quedó.

Respecto a sed.

Código (bash) [Seleccionar]
echo -e "$string" | sed "s/\.\///g"
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

sclub

#8
Claro!! El retraso fue que me quedé sin cargador del portatil...  :¬¬

Código completo:
Código (bash) [Seleccionar]
#!/bin/bash

IFS=$'\x0A'$'\x0D'

copiaRecurs() {
srcFolder="$1"
dstFolder="$2"

cd $srcFolder

for srcFile in $(find .)
do
srcFile=$(echo -e "$srcFile" | sed "s/\.\///g")
dstFile="$dstFolder/$srcFile"

if [ -d "$srcFile" ]; then
if [ ! -e "$dstFile" ]; then
mkdir -v "$dstFile"
fi
else
if [ ! -e "$dstFile" ]; then
cp -v "$srcFile" "$dstFile"
else
find "$srcFile" -cnewer "$dstFile" -exec cp -fv {} "$dstFile" \;
fi
fi
done
}

pathB="/media/BOX"
pathS="/media/STORE"

fldDAISrc="CFGS DAI2"
fldDAIDst="Workstore/CFGS DAI2"
fldSof="Softw"
fldDoc="Doc"
fldImg="Images"

if [ ! -d $pathB ]; then
echo -e "BOX isn't ready!"
exit
else
if [ ! -d $pathS ]; then
echo -e "STORE isn't ready!"
exit
fi
fi

echo -e "-----------------------"
echo -e " 1.- Update Software"
echo -e " 2.- Update Homework"
echo -e " 3.- Update Doc"
echo -e " 4.- Update Pictures"
echo -e " 5.- Update Everything"
echo -e "-----------------------"
echo -e " 6.- Custom Update"
echo -e "-----------------------"
read -p "  Option: " opc

case $opc in
1)
copiaRecurs "$pathB/$fldSof" "$pathS/$fldSof";;
2)
copiaRecurs "$pathB/$fldDAISrc" "$pathS/$fldDAIDst";;
3)
copiaRecurs "$pathB/$fldDoc" "$pathS/$fldDoc";;
4)
copiaRecurs "$pathB/$fldImg" "$pathS/$fldImg";;
5)
copiaRecurs "$pathB/$fldSoft" "$pathS/$fldSoft"
copiaRecurs "$pathB/$fldDAISrc" "$pathS/$fldDAIDst"
copiaRecurs "$pathB/$fldDoc" "$pathS/$fldDoc"
copiaRecurs "$pathB/$fldImg" "$pathS/$fldImg"
;;
6)
echo -e "----------------------------------------------"
echo -e " Both paths must exist before start copying!!"
echo -e "----------------------------------------------"
read -p "Enter the full source path: " srcCustom
if [ ! -d $srcCustom ]; then
echo -e "The path you provided do not exist!"
else
read -p "Enter the full destination path: " dstCustom
if [ ! -d $dstCustom ]; then
echo -e "The path you provided do not exist!"
else
copiaRecurs $srcCustom $dstCustom
fi
fi
;;
esac

echo "Cool!!"


Se me ha ocurrido ponerle una barra de progreso y alguna tonteria más, por trastear un poco más con bash, pero de momento ya cumple su función. :D

Gracias por la ayuda!
... because making UNIX friendly is easier than debugging Windows.