Crear varias imágenes de disco en batch

Preciso de ayuda para automatizar un proceso que de momento es bastante lento.

Resulta que realizo múltiples copias de seguridad que guardo en tarjetas sd, sirviéndome para ello de un un hub con 7 puertos usb al que le pongo las 7 sd, y cada vez que tengo que meterle una imagen a cada SD tengo que abrir 7 ventanas del programa Win32DiskImager y asignar cada una de las imágenes a cada ventana del programa, y esto con suerte de que no me pete windows al tener tantas ventas abiertas del Win32DiskImager. Entonces mi pregunta es:

¿Hay alguna manera de grabar varias SD simultaneas mediante un script de batch? Seria algo así como poner las diferentes unidades que corresponden a cada SD y si la unidad esta activa asignarle una imagen a cada una de ellas y que realice la copia.

Supongo que tiene que haber alguna manera.

1 Respuesta

Respuesta
1

No tengo muy claros algunos aspectos ni conozco la herramienta que utilizas (Win32DiskImager), de modo que voy a intentar aclararme:

1. ¿Cada imagen grabada en cada SD/USB es distinta de las otras? ¿Se trata de imágenes de carpetas o de unidades (discos)?

2. ¿Se conoce de antemano la "unidad" SD/USB de destino de cada imagen?

3. La herramienta Win32DiskImager, ¿permite ejecución en "modo comando"?

4. En las unidades SD/USB, ¿se guarda un histórico de imágenes? Si fuera así, ¿con qué criterio se borran las que se consideran obsoletas?

Si me aclaras estos puntos tal vez pueda intentar ayudarte a crear un bat. No sé si eso resultaría más ágil que el procedimiento que utilizas ahora pero sería cuestión de probarlo.

Intentare ser lo más claro posible a fin de facilitarte la tarea, por lo que contesto a tus dudas primero y luego te paso algunas imágenes de mi proceso:

1- Se trata de imágenes de disco pero que no tienen extensión ya que contienen cada una de ellas el sistema de archivos de Raspberry Pi (linux, distribución jessie) Desde windows aparecen como una partición que ocupa 60 megas solo, cuando en realidad son imágenes que ocupan 15 Gb.

-En principio todas las imágenes son iguales y las tengo que grabar en diferentes SD, pero hay casos en los que necesitaría grabar 2 imágenes distintas, pero de momento me conformo con que pueda grabar la misma imagen.

2- Sí, la letra de la unidad si se conoce, pues al insertar mi hub con 7 puertos y 7 SD en blanco me asigna siempre la misma letra para cada puerto (H, I, J, QUE, L, M, N,).

3- Win32DiskImager creo que no permite ejecución en modo comando, es muy simple el programa, es solo una ventana donde le dices la ruta de la imagen o la SD a copiar/grabar y listo, no tiene más opciones, si quieres echarle un vistazo es de licencia libre:

https://sourceforge.net/projects/win32diskimager/ 

4- En las SD no se guarda ningún histórico, o al menos que yo sepa.

--------------------

Bien ahora te intentare explicar con detalle lo que necesito y como hago ahora mismo las copias:

Tengo una carpeta creada en la siguiente dirección D:\Imagenes SD

Que contiene los siguientes ficheros:

Se trata de 7 imágenes de disco idénticas como te he comentado antes, y las he renombrado para asignarle a cada una su unidad de grabación.

Lo siguiente que hago es abrir 7 ventanas del Win32DiskImager y les asigno cada una de las unidades de las SD y les doy al botón write

Este proceso que parece rápido, se vuelve muy tedioso porque tengo que repetirlo varias veces al día, y de por sí es lento tener que abrir múltiples ventanas y asignarle su unidad de forma manual, por lo que con utomatizar alguna parte de este proceso quedaría realmente satisfecho.

He intentado yo varios métodos pero no he conseguido acabarlos:

Lo primero que intente es buscar una manera de copiar la imagen de la SD a windows mediante comandos .bat, y use el comando ROBOCOPY, pero solo me copia el contenido que puede leer windows el cual solo reconoce 60 MB pero lo que yo necesito es una imagen que ocupa 15 Gb.

En esta imagen puedes ver como la imagen de la SD windows solo reconoce 62,9 MB de los 15 reales que tiene la imagen:

Lo que supongo que hará falta es realizar algún comando previo que formatee la unidad de destino y que permita hacer una copia idéntica del disco, sin importar que windows no pueda reconocerlo, al fin y al cabo es para usarlas en otro sistema operativo.

La otra opción que he barajado es mediante un comando en .bat para automatizar lo que ya hago con el Win32DiskImager, me explico, seria crear un script que me abra 7 ventanas del programa y que mediante comando hacer que comience a grabar.

Hice esta prueba y la primera parte me ha funcionado: lo que hice fue ejecutar las 7 imágenes mediante el comando START, pero tenia el problema de que no tenían extensión y me pedía un programa para poder abrir la imagen, así que recurrí a la picaresca de añadirle una falsa extensión a las imágenes: ExclusivaTrebol *. D

Por lo que al ejecutar el siguiente comando consigo que se me habrán 7 ventanas de Win32DiskImager con su imagen conrrespondiente:

@ECHO OFF

START "" "D:\Imagenes SD\ExclusivaTrebol-0.d"
START "" "D:\Imagenes SD\ExclusivaTrebol-1.d"
START "" "D:\Imagenes SD\ExclusivaTrebol-2.d"
START "" "D:\Imagenes SD\ExclusivaTrebol-3.d"
START "" "D:\Imagenes SD\ExclusivaTrebol-4.d"
START "" "D:\Imagenes SD\ExclusivaTrebol-5.d"
START "" "D:\Imagenes SD\ExclusivaTrebol-6.d"

Hasta aquí bien, pero ya no se como hacer para asignar la letra de unidad correspondiente a cada Win32DiskImager ni como hacer que comience a grabar nada más abrir las ventanas, la verdad no se si es posible automatizar una ventana emergente haciendo que se pulse un determinado botón mediante batch.

Pues eso es toda la investigación que he podido hacer, creo que es un tema interesante para resolver porque no hay software que permita hacer múltiples copias de SD o USB y los aparatos duplicadores de SD tienen precios que oscilan desde los 450 hasta los 2000 euros, por lo que una solución mediante código para hacer múltiples copias de imágenes o unidades creo que facilitaría mucho la tarea a gente como yo que trabaja con bases de datos y respaldos, por eso he querido ser lo más explicativo posible para que todo el mundo entendiese un ejemplo concreto de lo que se podría hacer.

Muchas gracias por tu tiempo gggirald

Un saludo.

Por lo que he podido ver en

https://answers.launchpad.net/win32-image-writer/+question/189859

Efectivamente el Win32DiskImager no permite el "modo comando" y algunas otras personas ya lo han echado de menos, pero parece que los desarrolladores de la herramienta no se han decidido a incluirlo en las mejoras (o eso me ha parecido entender).

Sin embargo parece existir otra herramienta similar pensada para eso:

https://github.com/davidferguson/CommandLineDiskImager

Si es así y funciona, esta otra herramienta creo que podría ayudarte a hacer lo que quieres. Pero hay todavía una cosa que no me encaja o que no acabo de entender. Las imágenes que quieres copiar, ¿las genera el propio Win32DiskImager o se obtienen de forma independiente? En los ejemplos de la página anterior parece como si los archivos de imagen tuvieran la extensión IMG. Para hacer alguna prueba necesitaría un archivo de imagen. ¿Podría valer alguno generado con Nero, por ejemplo?

Hola buenas, si correcto, ese enlace que me has pasado es justo lo que yo busco, me lo he descargado y he estado leyendo un poco, he bajado una carpeta que contiene varios archivos y un ejecutable, pero cuando intento ejecutar el archivo me dice que windows no me permite abrirlo por seguridad.

Por lo que he leído en la página hay que abrir una ventana CMD como administrador y ubicarnos en esa carpeta del Command Line y usar el siguiente código:

CommandLineDiskImager.exe C:\Users\John\Downloads\raspbian.img G

esto lo que hace es buscar en esta ruta la imagen de disco: C:\Users\John\Downloads\raspbian.img 

Y la copia a la unidad G

Voy a ver si consigo algo haciéndolo tal cual lo explican.

En principio los archivos con los que yo trabajo no tienen ninguna extensión, estas imágenes las genera el propio Win32DiskImager, lo que se hace es colocar una SD que contenta el sistema de Raspbian (linux en la raspberri pi) y se inserta esa SD a un pc, supongamos que es la unidad H, pues abres el programa Win32DiskImager y seleccionas la unidad H, y luego eliges una ruta donde quieres que se copie esa imagen, y por ultimo le das al botón Read, de esta manera conseguimo hacer una copia exacta de la SD que contiene todo el sistema de archivos, y no tiene extensión este archivo creado. Eso respondería a tu pregunta supongo.

Para hacer tu la prueba con el mismo formato que uso yo haz lo siguiente que es muy fácil:

-Descárgate la imagen de raspbian de aquí:

https://www.raspberrypi.org/downloads/raspbian/ 

Esta imagen tiene formato .img y ocupa casi 4 gb sin comprimir.

-Luego inserta una SD o USB de más de 4gb y abre el programa Win32DiskImager, busca la ruta donde se encuentra la imagen que has descargado y después selecciona la letra de la unidad y le das a al botón WRITE, de esta manera copiamos el sistema operativo que has descargado a la SD.

-Lo siguiente que hay que hacer una vez que se ha copiado la información a la SD es duplicar esa tarjeta que has grabado, para ello abres de nuevo el Win32DiskImager y le das a la ruta del programa y le pones un nombre por ejemplo "pruebaSD" luego eliges la unidad donde se encuentra la SD a copiar, en el ejemplo era la unidad H y le das luego al botón READ

Con esta copia que hacemos lo que generamos es la imagen sin extensión como la que uso yo, esta imagen ocupa todo el ancho del espacio de la SD/USB es decir, si tu SD que has usado tiene 16 GB la imagen que creas con el Win32DiskImager sera de 16GB aunque el contenido real ocupe 4gb.

Pues con esa imagen ya puedes hacer pruebas haber si el command line ese nos puede servir.

Un saludo!

Ayer estuve haciendo unas pruebecillas limitadas del CommandLineDiskImager.exe. Trabajo con XP y no he tenido ningún problema para ejecutarlo. Si que he visto dos cosas: que el indicador de la unidad tiene que estar en mayúsculas y que la información de avance de la grabación no se superpone sino que se añade con lo que resulta un poco inservible. Imagino que esto segundo se puede arreglar configurando el tamaño de la ventana CMD. Aparte de estas "peculiaridades" que a mi modo de ver hacen que desmerezca un poco el "producto", el comando parece funcionar como se espera. No voy a poder probar mucho hoy porque tengo el día un poco liado. Te sugiero que pruebes tú y si tienes algún problema me lo comentas y vemos si se nos ocurre algo.

He visto que has abierto otra consulta en MSDOS. Te la voy a contestar allí.

He probado yo pero algo estaré haciendo mal porque a mi no me funciona:

Haber yo abro CMD con permisos de administrador y me sitúo en la ruta donde se encuentra el Command Line, en mi caso:

D:\Imagenes SD\CommandLineDiskImager

Luego una vez situado en la ruta anterior lo que hago es ejecutar este comando:

CommandLineDiskImager.exe D:\Imagenes SD\ExclusivaTrebol-0 E

La E final hace referencia a la unidad donde tengo la SD para grabar, y también le indico la ruta donde se encuentra la imagen.

Ya me dices que es lo que hago mal.

Un saludo

¿Qué mensaje te da la ejecución de ese comando?

Te pongo como ejemplo lo que me sale a mí. Utilizo un archivo img obtenido con Nero a partir de un CD para que no sea demasiado grande (se genera como nrg y lo he renombrado a img):

Microsoft Windows XP [Versión 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\Documents and Settings\GGG>c:\utilidades\CommandLineDiskImager\CommandLineDiskImager c:
\tmp\Image.img F
writing file c:\tmp\Image.img to device F:0/106868525600/106868551200/106868576800/1068685
102400/1068685128000/1068685153600/1068685179200/1068685204800/1068685230400/1068685256000
/1068685281600/1068685307200/1068685332800/1068685358400/1068685384000/1068685409600/10686
85435200/1068685460800/1068685486400/1068685512000/1068685537600/1068685563200/10686855888
00/1068685614400/1068685640000/1068685665600/1068685691200/1068685716800/1068685742400/106
8685768000/1068685793600/1068685819200/1068685844800/1068685870400/1068685896000/106868592
1600/1068685947200/1068685972800/1068685998400/10686851024000/10686851049600/1068685
info - write successful

Los numeritos que salen informan (un poco mal, eso sí) del avance de la escritura. Son algo así como los bytes escritos y los que tiene que escribir. Correctamente separados deberían ser algo como:

writing file c:\tmp\Image.img to device F:
0/1068685
25600/1068685
51200/1068685
76800/1068685
102400/1068685
128000/1068685
153600/1068685
179200/1068685
204800/1068685
230400/1068685
256000/1068685
281600/1068685
307200/1068685
332800/1068685
358400/1068685
384000/1068685
409600/1068685
435200/1068685
460800/1068685
486400/1068685
512000/1068685
537600/1068685
563200/1068685
588800/1068685
614400/1068685
640000/1068685
665600/1068685
691200/1068685
716800/1068685
742400/1068685
768000/1068685
793600/1068685
819200/1068685
844800/1068685
870400/1068685
896000/1068685
921600/1068685
947200/1068685
972800/1068685
998400/1068685
1024000/1068685
1049600/1068685

Acabo de ver una posible causa de tus problemas. Veo el comando que escribes es:

CommandLineDiskImager.exe D:\Imagenes SD\ExclusivaTrebol-0 E

Con un espacio entre "Imagenes" y "SD". Si es así deberías poner entre comillas el path del archivo origen. Así:

CommandLineDiskImager.exe "D:\Imagenes SD\ExclusivaTrebol-0" E

Estupendo! Ya me funciona, eres un crack!

He grabado una de mis imágenes sin formato y la ha grabado, luego cuando tenga tiempo revisare si se ha grabado correctamente todo el contenido y si es así ya tendré que hacerme un script en .bat en el que si hay unidades activas que me las grabe, también tendré que probar como se comporta el código al grabar 7 imágenes simultaneas.

Haber si lo dejo todo listo para que con un clic pueda grabarde forma sencilla.

Saludos!

Yo creo que sería mejor que las grabaciones se hagan consecutivamente y no de forma simultánea. Mi impresión es que se tarda menos de la primera forma. Por otra parte tampoco tengo muy claro como se lanzarían las grabaciones simultáneas, supongo que con el comando START.

Te propongo que hagas una prueba controlada de grabación simultánea o consecutiva en dos SD, tomando instantes de inicio y de final para poder comparar. Según el resultado de la prueba podrás elegir una u otra modalidad.

Hola muy buenas! Pues he estado haciendo pruebas y he grabado una SD y he medido tiempo y luego he grabado 3 simultaneas, y cuando grabe 3 simultaneas me tardo 25 minutos frente a 19 minutos cuando grabe solo 1, por lo que me trae cuenta grabar varias simultaneas pues el tiempo me parece más que razonable.

Ahora me queda adaptarlo un poco a mi gusto y que quede algo más cómodo de usar, el tema de que aparezca la ventana llenándose de datos mientras se copia no me gusta nada, he intentado ver si hay alguna otra forma de que muestre que esta copiando o mediante barras de progreso pero creo que no es posible en el entorno de ms-dos, por lo que me conformaría con ponerle al script algún aviso de que se ha grabado satisfactoriamente la unidad X y que me avise de que ha comenzado a grabar en tal unidad.

Por lo demás estoy muy contento con el logro de grabar de esta manera, es mucho más estable la copia que usando 10 ventanas del otro programa que me daba muchos errores al grabar.

Un saludo.

Muy bien. Aunque no se confirme lo que yo intuía creo que es muy bueno saber a que atenerse. ¿Cómo lanzas las copias simultáneas? ¿Con START?

Para evitar la salida de esa molesta ristra de datos puedes forzar que se ignore la salida añadiendo "> nul". Quedaría así:

CommandLineDiskImager.exe "D:\Imagenes SD\ExclusivaTrebol-0" E > nul

Si quieres puedes plantearme el esquema de tu bat por si puedo echarte una mano en algo. Por mi parte voy a ver si consigo algo para que el bat vaya indicando el inicio y el final de las grabaciones, aunque no tengo todavía claro como podría hacerlo.

Te muestro lo que he hecho con mi código en bat:

@echo off
title JSGrabacion

Color b0
ECHO Se va a proceder a la Grabación

PAUSE

D:
CD D:\Imagenes SD\CommandLineDiskImager

msg * "ࠅesta seguro?" se borrara el contenido de las siguientes unidades (G:) (M:)

START CommandLineDiskImager.exe "D:\Imagenes SD\ExclusivaTrebol-1" M
timeout /t 1 /nobreak
msg * "Tarjeta unidad M: grabada correctamente"

START CommandLineDiskImager.exe "D:\Imagenes SD\ExclusivaTrebol-2" G
timeout /t 2 /nobreak
msg * "Tarjeta unidad G: grabada correctamente"

PAUSE
EXIT

Como ves he usado el comando START, pero me surgía el problema de que como se ejecutaba de forma simultanea 2 o más acciones importantes, pues a veces si me graba las 3 SD pero a veces me graba solo 1 o 2, por lo que supuse que habría que darle algo de tiempo entre cada comando, asique he probado a hacerle un retardo de un segundo entre cada comando START y ahora parece que siempre funciona como debe.

Por otro lado he estado haciendo pruebas de como poner ventanas emergentes para que me avisen con un mensaje de advertencia que se van a grabar las unidades y también unos mensajes cuando haya finalizado el proceso de grabación.

El problema que no me funciona bien pues los mensajes de "grabación finalizada" me aparecen a la misma vez de cuando empiezo a grabar, supongo que todo este proceso habrá que hacerlo mediante variables o con el uso de IF y ELSE, pero en ese terreno ando más escaso de ideas.

La idea básicamente es:

-El programa me tiene que advertir al inicio mediante un mensaje de que se borrara el contenido de las unidades "X" y si acepto la ventana, comenzara la grabación de las SD.

-En este punto pueden pasar 2 cosas:

A- Que la unidad extraíble si se encuentra disponible con lo que comenzaría a grabar directamente sin problemas.

B- Que la unidad extraíble no se encuentre disponible o este mal insertada, con lo cual me debe salir un mensaje diciendo "Unidad POR no esta disponible"

(De esta forma yo puedo saber si alguna de las muchas SD que tengo grabando no esta insertada o esta insertada mal)

-Una vez que cada una de las unidades ha terminado de grabar me debe de mostrar un mensaje que ponga "Unidad POR grabada con éxito"

Ya lo otro que queda pendiente es intentar que mientras se graba cada SD que aparezca algo que me muestre el progreso de la grabación, aunque sea mediante cifras pero que no aparezca esa ventana tan fea y grande mostrando tantas líneas, si no se puede conseguir, prefiero que no se vean esas ventanas, porque ver 7 ventanas enormes mostrando información confusa es preferible que no estén.

Gracias una vez más Gggirald. Un saludo.

Esto es lo que creo que podría servirte:

1. Crear un bat, al que yo he llamado CLDIW.BAT (de CommandLineDiskImageWriter) que se encargará de las grabaciones particularizadas en cada unidad. Sería algo así:

:: Para grabar en disco una imagen (unidad, imagen)
@echo off
dir /b %1: 2>present%1.txt
for /f "tokens=5,*" %%i in (present%1.txt) do (if %%i==hallar goto :noesta)
if not exist %2 goto :sinImagen
set /p Es_grabar=Se va a borrar todo el contenido de la unidad %1:. ¨Seguro (S/N)?
if %Es_grabar%==S goto :grabar
if %Es_grabar%==s goto :grabar
goto :fin
:grabar
echo Va a comenzar la grabacion en %1: %date% %time%
c:\utilidades\CommandLineDiskImager\CommandLineDiskImager %2 %1 > nul
if errorlevel 0 echo Ha terminado la grabacion en %1: %date% %time%
pause
goto :fin
:noesta
echo No hay disco en la unidad %1:&goto :fin
:SinImagen
Echo No existe archivo imagen %2
:Fin
exit

Lógicamente el path que le he puesto al CommandLineDiskImager.exe tendrías que ajustarlo a tu caso.

2. El BAT principal, encargado de lanzar, de forma concurrente, las grabaciones en las distintas unidades. He partido de un mismo archivo de imagen y no de uno para cada destino. Si tuviera que ser uno para cada destino tal vez sería mejor no usar un bucle FOR y crear explícitamente un START para cada unidad de destino. Sería algo así:

@echo off
for %%u in (H, I, J, K, L, M, N) do start d:\bat\cldiw %%u c:\tmp\Image.img

Lógicamente el path del CLDIW.BAT y del archivo imagen habría que ajustarlos a tu entorno.

No estoy muy satisfecho de la forma de controlar que la unidad destino está montada (no me gusta tener que usar un archivo intermedio PRESENTu.TXT para ello, pero de momento no se me ha ocurrido otra forma).

Mira a ver que tal te funciona y cuéntame algo.

 Hola muy buenas, he hecho una prueba rápida con el el código que me has pasado pero algo estaré haciendo mal porque no me funciona, yo lo que hecho es guardar en un .bat el primer código y lo he llamado "CLDIW.BAT" y dentro de ese código he colocado la ruta de mi CommandLine y luego he creado otro archivo bat llamado PRIMER.BAT y he colocado la ruta del otro archivo bat y luego he colocado la ruta donde se encuentra mi Imagen para grabar, este es el codigo:

@echo off
for %%u in (H, I, J, K, L, M, N) do start "C:\Users\Mario\Desktop\APRENDER BATCH\Prueba\CLDIW.BAT" %%u "D:\Imagenes SD\ExclusivaTrebol"

Pues cuando ejecuto el bat anterior me sale lo siguiente:

Seguramente no entendí algo. Un saludo.

Desde luego da la impresión de que los START del bucle FOR del PRIMER.BAT no están arrancando el CLDIW.BAT sino que intentan arrancar el %%u (que contiene, sucesivamente, los nombres de las unidades). Como no son archivos no puede arrancarlos y por eso salen esos errores. Intuyo que tiene que ver con las comillas, necesarias, en principio, si las carpetas tienen espacios en el nombre pero que no sé si el START las trata correctamente. Mañana probaré esta línea de investigación, pero si quieres puedes probar a ubicar, tanto el CLDIW como la imagen, en carpetas sin espacios en los nombres, a ver que pasa.

He conseguido reproducir lo que te ocurre sin más que poner entre comillas la invocación al CLDIW.BAT en el comando START. Sustituí la línea del FOR que puse ayer por la siguiente:

for %%u in (H, I, J, K, L, M, N) do start "d:\bat\cldiw" %%u "c:\tmp\Image.img"

Viendo la ayuda del START caí en la cuenta de que estaba tomando como título el primer parámetro entrecomillado. Le puse otro, incluso uno vacío, y de esa manera ya no interpreta la unidad (%%u) como el archivo a ejecutar, pero tampoco funciona. Abre las ventanas pero en cada una de ellas dice que "El nombre de archivo, directorio o etiqueta del volumen no es válido." Si dejo sin comillas la referencia al archivo de imagen sí que funciona. Y esto último no consigo entenderlo.

De momento podrías ubicar el CLDIW.BAT en el mismo directorio que el PRIMER.BAT y así este PRIMER.BAT podría ser:

@echo off
for %%u in (H, I, J, K, L, M, N) do start CLDIW.BAT %%u "D:\Imagenes SD\ExclusivaTrebol"

Creo que así funcionaría sin problemas. Ya me dirás.

Muy buenas! He colocado los dos archivos juntos y he hecho las modificaciones que me comentas, he probado a grabar y ahora si que se me habre una ventana por cada unidad preguntandome si quiero empezara grabar s/n, el problema es que si digo que si me sale el mensaje de ha comenzado a grabar y a terminado de grabar, los dos a la vez, y en verdad no graba, te paso imagen:

entonces supuse que es porque no he dado permisos de administrados a CMD, que ya me paso, pues bien, al dar permisos de administrador y ejecutar el mismo programa me sale el siguiente error:

así por cada una de las unidades, curiosamente si ejecuto el batch sin permisos de administrador me sale lo que te he comentado al principio pero no llega a grabar.

Ya me cuentas que puede ser, un saludo

En vista de lo que me comentas he considerado que ya había llegado la hora de pasar a probar en Windows10 (soy un poco vago y mi sobremesa tiene el XP, al que le tengo mucho cariño). He podido comprobar que, efectivamente, necesito ser administrador para que me deje escribir en el destino y que, además, al entrar como administrador la carpeta de destino por defecto no es la de usuario sino c:\WINDOWS\system32. Esto explicaría lo que muestras en la ejecución segunda, en la que está claro que no encuentra el CLDIW.BAT. Evidentemente no se está ejecutando en el directorio adecuado, pero en el pantallazo no se ve el directorio de ejecución. Tienes que situarte en el directorio adecuado antes de ejecutar el PRIMER.BAT (eso se puede incorporar al PRIMER.BAT añadiendo un comando CD a la carpeta correcta antes del FOR). Además he visto que el mensaje en el que me basaba para decidir que los discos no estaban montados como respuesta al comando (DIR /B unidad:) es ligeramente diferente en Windows10 y esa ligera diferencia afecta, (¡que p. casualidad!) A la "palabra clave" que utilizo. Total, que habría que cambiar en el CLDIW.BAT "hallar" por "encontrar" en la línea del FOR.

Por tanto:

1. Corrige el CLDIW.BAT en el sentido indicado si un comando como "DIR /B H:" te contesta "El sistema no puede encontrar la ruta especificada." cuando no haya nada en la unidad H:

2. Añade al PRIMER.BAT unos comandos para situarte en la carpeta donde tengas PRIMER.BAT y CLDIW.BAT antes de ejecutarlo. Por ejemplo, si están en d:\

Se me ha escapado el mensaje cuando intentaba borrar algo. Repito el segundo punto:

2. Añade al PRIMER.BAT unos comandos para situarte en la carpeta donde tengas PRIMER.BAT y CLDIW.BAT antes de ejecutarlo. Por ejemplo, si están en C:\Users\Mario\Desktop\APRENDER BATCH\Prueba tendrás que añadir, antes del FOR, el comando:

cd "\Users\Mario\Desktop\APRENDER BATCH\Prueba"

3. Entra en CMD como administrador y ejecuta el PRIMER.BAT

4. Me cuentas como te ha ido.

Esto ya tiene mejor pinta, tras realizar los cambios que me has mencionado ahora solo se me habren tantas ventanas como SD tengo listas para grabar, es decir, como tengo 2 SD listas pues me aparecen 2 ventanas preguntándome si quiero iniciar la grabación, le doy a si, y me sale el mensaje de que "va a comenzar la grabación" pero se queda la ventana sin aparecer ningún dato más, no se si es porque me has ocultado los datos que se están grabando o es un error, me esperare media hora y te comento si se graba al final, lo tengo así de momento:

Hay una cosa que no entiendo, si al iniciar el programa ya me aparecen las ventanas de las SD que tengo insertadas, ¿entonces la parte del código encargada de que me salga el mensaje de "La SD no se encuentra insertada" eso ya no me valdría no? Ya que el programa sabe cuando tengo una SD y en que volumen, lo que si me vendría bien que me diera algún aviso si se corta la grabación o si no es posible grabar en la SD por ejemplo si esta dañada.

Un saludo

Efectivamente, he ocultado la salida progresiva de la grabación (en realidad he tirado con el "> nul"). Si esperas lo suficiente acabará saliendo el mensaje de fin de grabación. Y tienes razón, dado que solo se te abren las ventanas de las SD que están listas el mensaje "No hay disco en la unidad X:" no llegas a verlo tal como está el CLDIW.BAT. Eso se podría arreglar moviendo el comando "pause" de su posición actual (detrás del "if errorlevel 0...") a la penúltima posición, antes del "exit". De todas formas tal vez fuera buena idea guardar los mensajes en un archivo de log que puedas revisar después. Creo que si hay problema en la grabación debe salir en la ventana correspondiente porque la salida de error no está redirigida a nul, pero eso puede depender de la estructura interna de la propia herramienta. Si puedes provocar errores de grabación no estaría de más hacerlo para tomar alguna decisión. Porque siempre se podría hacer que las horrorosas salidas numéricas del comando se guardaran, también, en el log, o en otro log diferente.

Todo eso ya serían mejoras en el proceso, para las que puedes contar conmigo, pero tienes que saber lo que quieres, claro.

Me funciona perfectamente! Pues si quiero ir mejorándolo, pero de momento hace lo más importante que son las copias desatendidas, esto me quita ya muchísimo trabajo, ya las demás mejoras son estéticas o de ampliar funcionalidad para mayor comodidad.

Lo que voy a hacer es sobre tu script ir trabajándolo e intentar añadirle más funciones, porque mi idea es hacerme un pequeño menu de navegación en el que pueda elegir por ejemplo copiar muchas SD (seria en este caso tu código) o grabar una única SD en una unidad que especifica el usuario, o realizar una duplicación a partir de una SD... al final con esto lo que obtenemos es un programita muy completo y muy superior a lo que hay ahora mismo, eso si, más feo, pero seguro que hay más gente que valora el lado funcional de las cosas.

Cuando tenga todo más avanzado y tenga alguna duda importante te la comentare por aquí y cuando acabe esto lo compartiré por aquí pues seguro que va a ser de mucha utilidad a más gente.

Una ultima cosa que veo así a bote pronto mejorable y no se si hay alguna manera "facil" de conseguirla, ya he cambiado de intentar el PAUSE por lo que ya me muestra las ventanas de las unidades que no tienen SD, esto esta muy bien, y de hecho a mi me gusta verlo, el problema es que se vuelve algo caótico que se abran tantas ventanas tan grandes y de forma desordenada, que no puedes ni cerrarlas fácilmente, con lo cual estaría bien unificar en una sola ventana por ejemplo todos los mensajes informativos de que "no esta tal unidad" para ahorrar así espacio en ventanas, otra opción que también me valdría es hacer las ventanas más pequeñas y que se mostraran de forma ordenada o desplegadas en una determinada intentar.

Un saludo!

Mira seria algo así, con las ventanas más pequeñas:

Otra opción podría ser lanzar ventanas informativas de windows con el comando msg* diciendo que unidades no están disponibles, cualquiera de las opciones me valdría.

Me autorrespondo:

He hecho yo la prueba para las unidades que no tienen SD y que me informe con mensajes de windows, y me gusta por que es más ordenado y cómodo aceptar estas ventanitas:

Lo que he hecho es quitar el Pause del final y en el código he cambiado esta parte:

:no esta
msg * "No hay disco en la unidad %1":&goto :fin

Ahora lo único que me haría falta es ubicar las ventanas de grabación de una manera más ordenada o haciéndolas más pequeñas.

Saludos

Muy bien. Me alegro que vaya estando a tu gusto. Si hay algo en lo que creas que te puedo ayudar avísame.

Lo que apuntas de cambiar el tamaño de las ventanas, ya abiertas por el comando START, no sé si puede hacerse, o si ya no te vale la pena si usas el comando MSG (comando que debo decir que no conocía y que me apunto).

Si se traslada al programa principal el "análisis" del montaje de las unidades y solo se lanza el START para las unidades que están montadas podría conseguirse lo que dices de agrupar los mensajes de "no está".

Hoy he estado usando el programita y grabando SD de 7 en 7 y tarda 40minutos en hacer la copia de las 7, con lo que estoy muy satisfecho con el resultado. Esto me ha servido para darme cuenta de algunas cosas, por ejemplo si por error toco una SD y deja de grabarse (los usb grabadores que uso son del chino) pues el programa da por hecho de que se ha grabado y me sale el mensaje de "tarjeta SD grabada" antes de tiempo, lógicamente esta grabación no sirve y me doy cuenta ya que no es normal que se termine de grabar antes de 10 minutos, con lo que mi pregunta es:

¿Hay alguna forma mediante algún comando que se pueda decir que si finaliza la grabación antes de que la tarjeta no alcance los 30253056 bites (ya que yo siempre grabo en tarjetas de 16 gigas) que me de un mensaje de error, si no se pudiera hacer con los datos de la transferencia me conformaría con algún parámetro de tiempo, por ejemplo si la grabación ha tardado menos de 20 minutos que me salga un mensaje de error "la SD no se ha grabado correctamente".

Esto es muy importante para mi ya que comovoy grabando de 7 en 7 a veces pasa que alguna no se ha grabado correctamente y no me doy cuenta, y como suele pasar en los primeros minutos siempre los errores de grabación pues de esta forma me evitaría muchos problemas.

No se bien en que consiste el comando "if errorlevel 0 " que usas para determinar que la SD se ha completado, pero seria sustituir eso o ponerle más seguridad a ese comando para evitar que si no se graba completamente la SD no me la de por valida.

Por cierto a raíz de esto se me ocurrió una idea muy ingeniosa de controlar el progreso de la grabación, si consigues algún método por ejemplo lo que te he comentado antes mediante sectores grabados, se puede hacer una barra de progreso en batch mediante códigos y que se vaya mostrando según el progreso, por ejemplo si la SD tiene 30253056 de espacio estando al 100 por cien grabada le asignaría este código:

if 2404
echo ±±±±±±±±±±±±±±±±±±±±±±±±±±±
cls

if 48563
echo ÛÛ±±±±±±±±±±±±±±±±±±±±±±±±±
cls

if 69565
echo ÛÛÛÛ±±±±±±±±±±±±±±±±±±±±±±±
cls

if 104564
echo ÛÛÛÛÛÛÛ±±±±±±±±±±±±±±±±±±±±
cls

if 2346584
echo ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ±±±±±±±
cls

if 30253056
echo ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

Echo Grabación completada!

No tomes al pie de la letra lo que te he pasado, me he inventado lo del if, pero los símbolos esos que tehepuesto si los ejecutas en un .bat se ven igual que una barra de progreso, entonces si mientras se graba la SD en un documento en segundo plano sabemos los datos que se han transferido a la SD pues nos irira mostrando la barra completándose, lógicamente cuanto más rango y más dibujos de estos se hagan más preciso sera el progreso de la barra, pero con tener 5 o 6 extracciones de datos seria suficiente, lo mismo que te he comentado antes, si no es posible saber los bytes del progreso de la SD, me conformaría con un control por tiempo, mucho más impreciso, pero si la SD me tarda 40 minutos en grabarse pues seria mostrar cada 5 minutos por ejemplo una barrita llenándose, cuando hayan pasado 20 minutos pues se mostraría esto:

Echo ÛÛÛÛÛÛÛÛÛÛÛÛÛ±±±±±±±±±±±±±±±±±±±

Esto es más ingenio que otra cosa, pero al fin y al cabohace su función, y mato dos pájaros de un tiro, lo primero que consigo es evitar que tome por validas tarjetas que no se han terminado de grabar y lo segundo que es lo de la barra de progreso, que aunque es "decorativo" siempre viene bien.

Un saludo!

A ver que te digo.

Empezaré por lo más fácil. Errorlevel es una variable del sistema (a la que se tiene acceso bien con el "if errorlevel" o como %ERRORLEVEL%) que recoge el "resultado" de la última ejecución de un comando, un bat o un programa. Puedes ver la ayuda tecleando "if /?" en una ventana CMD y la peculiaridad de que "if errorlevel N" es cierta si el errorlevel es igual o mayor que N. Cuando es un comando interno de MSDOS normalmente los valores se pueden usar para saber que ha pasado. El valor 0 significa que la ejecución ha ido bien y otros valores significan que no ha ido bien, pero cada comando tiene una forma de codificar el error diferente. Cuando es un bat se puede controlar la codificación desde el propio BAT con un "exit /b nnn" (en el que nnn es el número que se quiere asignar al errorlevel) antes de cerrar el BAT. Cuando es un programa el diseñador del programa es el responsable del valor del errorlevel cuando el programa finaliza. Y este, creo, es nuestro caso. Si el diseñador del programa hubiera previsto un código de salida mayor que cero cuando el programa CommandLineDiskImager.exe detectara un error no valdría cero y no saldría el mensaje "Ha terminado la grabación..."

Había empezado a contarte esto y me di cuenta que en realidad no había previsto un valor mayor que cero como indicador del error. Y he decidido probarlo antes de seguir. Y creo que tengo buenas noticias.

Coloca en el CLDIW.BAT antes del "if errorlevel 0" la instrucción:

if errorlevel 1 echo Ha habido error en la grabacion en %1: %date% %time%&goto :fin

Y prueba a ver si detecta los errores provocados (creo que lo hará) y me cuentas. Si funciona ya no sigo con el rollo que tenía en mente.

Cojonudo funciona! Ahora si por ejemplo extraigo la SD mientras esta grabándose o se corta por otro motivo me salta "ERROR en la grabación" supongo que si se termina de grabar correctamente me saldrá el mensaje de "Grabado correctamente"

Ahora me queda ver que tipo de datos de la grabación puedo usar para crear la barra de progreso, te mantendré informado.

Saludos!

He encontrado el siguiente código para hacer funcionar una barra, parece que funciona mediante ping, quizás con la variable que se usa en la grabación pueda valer:

@echo off
rem by Germaniac
SetLocal EnableDelayedExpansion EnableExtensions
Echo.
Echo. Cargando.....
Echo.
Set "bar="
Set "percent=0"
Set "count=0"
For /L %%I In (1,1,20) Do (Set "bar=!bar!±")
:Loop
Set /P "= %bar:~0,20% %percent%%%"
REM en esta linea seteo la variable asdf = al primero numero del comando random (cualquier numero del 1 al 9)
Set "asdf=%Random:~0,1%"
If %asdf% GEQ 8 (
REM acá si la variable asdf es mayor o igual a 8 le resto 4 para que el ping no pase de 5 y así no hace tan larga la carga
Set /A "asdf=asdf-4"
)
REM y acá solo cambio los ping 5 por el lo que contenga la variable asdf
Ping -n %asdf:~0,1% -w %asdf:~0,1% LocalHost>nul
For /L %%I In (1,1,26) Do Set /p "= "
Set "bar=Û%bar%"
Set /a "count+=1"
Set /a "percent+=5"
If %count% LEQ 20 Goto:Loop
Echo.
Echo.
Echo. Cargado.
Pause>Nul 2>&1
Exit

Con esto entramos en el rollo del que hablaba.

El problema de este programita es que el control de los valores que saca lo tiene el propio programa, no el bat desde el que se le invoca. Eso impide tratarlo desde el bat. Por un lado habría que quitar el "> nul" que "tira" lo que el programa saca, pero además no se puede tratar independientemente cada ristra de números porque el programa no se para. En tu ejemplo es el bat el que controla lo que ocurre. Si hubiera alguna forma de hacer que el programa CommandLineDiskImager.exe grabara bloque a bloque podría el bat tener el control de los bloques grabados y montar algo con ello, pero no parece que haya ninguna manera de hacerlo. Yo creo que no se puede aplicar. Otra cosa sería guardar en un archivo aparte los numeritos que saca y tratarlos "a posteriori" pero eso, que nos permitiría montar la barra, no sería un reflejo de lo que está ocurriendo sino de lo que ha ocurrido.

Me he puesto a investigar la posibilidad de establecer una barra de progreso, tal como sugerías. Como decía el problema para incluir la barra en el bat de grabación era que la marcha de la grabación la controla la herramienta CommandLineDiskImager.exe sin devolver el control al bat. Se me ocurrió que se podría hacer con otro proceso, ejecutado en paralelo, que controlara los números que genera la herramienta, grabados en un log. Y creo que ya lo tengo. Habría tres BAT:

1. El BAT de control general, al que he trasladado el control de las unidades "montadas" que sería algo como:

@echo off
Setlocal EnableDelayedExpansion
for %%u in (H, I, J, K, L, M, N) do (
   set unidad=%%u
   dir /b !unidad!: 2>present!unidad!.txt
   for /f "eol=A tokens=5,*" %%i in (present!unidad!.txt) do (
      if %%i==encontrar (echo no hay disco en !unidad!:
      ) else start "" cldiw_c !unidad! c:\tmp\Image.img
   )
)

2. El BAT que lanza tanto la herramienta de grabación, como el BAT de control de progreso para las unidades montadas (al que he llamado CLDIW_C.BAT, por lo del control, y a él me refiero en el primer BAT, línea del "else"):

:: Para grabar en disco una imagen (unidad, imagen)
:: Según la versión de Windows y los permisos puede ser necesario ajustar el filtro del TASKLIST
@echo off
title=cldiw_%1
if #%1#==## goto :sinDisco
if not exist %2 goto :sinImagen
set /p Es_grabar=Se va a borrar todo el contenido de la unidad %1:. ¨Seguro (S/N)?
if %Es_grabar%==S goto :grabar
if %Es_grabar%==s goto :grabar
goto :salir
:grabar
echo Va a comenzar la grabacion en %1: %date% %time%
start "Control grabacion unidad %1" GrabCont %1
c:\tmp\CommandLineDiskImager\CommandLineDiskImager %2 %1 > Grab%1.log
if errorlevel 1 echo Ha habido error en la grabacion en %1: %date% %time%&goto :fin
if errorlevel 0 echo Ha terminado la grabacion en %1: %date% %time%
goto :fin
:sinDisco
echo No se ha indicado unidad&goto :salir
:sinImagen
echo No existe el archivo imagen %2
:fin
pause
for /f "tokens=2,3* delims= " %%a in ('tasklist /NH /FO TABLE /FI "WINDOWTITLE eq Administrador: =GrabCont%1"') do (
taskkill /PID %%a > nul
)
:Salir
exit

3. El BAT de control de progreso de las grabaciones, al que he llamado GRABCONT.BAT, y que lanzo con la línea del "start" del BAT anterior:

:: Se encarga de controlar el progreso de la grabación en la unidad correspondiente
:: Si el proceso de grabación es muy lento puede ser necesario reajustar la temporización del ping anterior al bucle
:: Si es insuficiente puede dar un error tipo "No se esperaba ( en este momento" o alguna similar
@echo off
title=GrabCont%1
mode con lines=4
mode con cols=40
Setlocal EnableDelayedExpansion
ping -n 2 localhost >nul
for /f "tokens=7,8* delims=/ " %%a in ('type Grab%1.log') do set max=%%a
set cifra=%max%
set /a cifMax=1
:cuentacifras
set cifra=%cifra:~1%
if defined cifra set /a cifMax+=1&goto:cuentacifras
ping -n 10 localhost >nul
:bucle
for /f "tokens=*" %%a in ('type Grab%1.log^|find "writing"') do set grabados=%%a
set /a pos=1
set ind=n
:buscar
set car=!grabados:~-%pos%,1!
if %car%==/ (
   if %ind%==s (
      goto :seguir
      ) else set ind=s&set /a aux=%pos%
)
set /a pos+=1
goto :buscar
:seguir
set /a aux=%pos%-%aux%-%cifMax%-1
set /a pos=%pos%-%cifMax%-1
set grabados=!grabados:~-%pos%,%aux%!
set /a porcentaje=%grabados%00/%max%
set /a cuadros=%porcentaje%/5
cls
set bar=±±±±±±±±±±±±±±±±±±±±
for /l %%i in (1,1,%cuadros%) do set bar=Û!bar!
echo %bar:~0,20% %porcentaje%%% grabado
if %porcentaje% geq 98 goto :fin
ping -n 1 localhost >nul
goto :bucle
:fin
pause
mode con lines=25
mode con cols=90

He aprendido, de paso, a controlar el tamaño de la ventana de este bat para que sea lo más pequeña posible. Le he puesto un "pause" al final del que se puede prescindir porque el CLDIW_C que lo lanza lo mata al terminar la grabación (comando TASKKILL) si todavía estuviera activo. No llega a controlar el 100% de la grabación porque la herramienta no envía la última información de grabación, por eso le he puesto que "porcentaje" sea mayor o igual que el 98% para darlo por finalizado. Mira a ver si se adapta a tus necesidades y me dices algo.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas