# Saber qué disposivos de bloque son Flash USB

## johnlu

¿Como podría saber qué dispositivos de /dev/sd* son memorias USB Flash?

Lo necesito para un instalador de LiveUSB que estoy haciendo. Está escrito usando C++ con Gtkmm.

----------

## agdg

Desconozco la existencia de un comando bash que permita hacer tal cosa, pero se me ocurren el siguiente camino a seguir:

/dev/disk/by-path/

Ahí obtendrás información acerca de los dispositivos pinchados, tan solo tendrás que hacer un filtro usando usb como palabra clave:

```
[agd@agd-desktop]$ ls -lh /dev/disk/by-path/ | grep usb

lrwxrwxrwx 1 root root  9 oct  6 00:25 pci-0000:00:1d.7-usb-0:3:1.0-scsi-0:0:0:0 -> ../../sdl

lrwxrwxrwx 1 root root 10 oct  6 00:25 pci-0000:00:1d.7-usb-0:3:1.0-scsi-0:0:0:0-part1 -> ../../sdl1

lrwxrwxrwx 1 root root  9 oct  1 12:04 pci-0000:00:1d.7-usb-0:4:1.0-scsi-0:0:0:0 -> ../../sdg

lrwxrwxrwx 1 root root  9 oct  1 12:04 pci-0000:00:1d.7-usb-0:4:1.0-scsi-0:0:0:1 -> ../../sdh

lrwxrwxrwx 1 root root  9 oct  1 12:04 pci-0000:00:1d.7-usb-0:4:1.0-scsi-0:0:0:2 -> ../../sdi

lrwxrwxrwx 1 root root  9 oct  1 12:04 pci-0000:00:1d.7-usb-0:4:1.0-scsi-0:0:0:3 -> ../../sdj

lrwxrwxrwx 1 root root  9 oct  1 12:04 pci-0000:00:1d.7-usb-0:4:1.0-scsi-0:0:0:4 -> ../../sdk
```

Como ves, tengo bastantes "dispositivos usb" y curiosamente todos, salvo uno, están sin montar. ¿Respuesta fácil no? El lector multitarjeta. Actualmente el único disco "usb usable" es sdl con una única partición sdl1.

Si solo precisamos los dispositivos usb de almacenamiento "activos", basta con agregar un grep part:

```
[agd@agd-desktop Chrome]$ ls -lh /dev/disk/by-path/ | grep usb | grep part

lrwxrwxrwx 1 root root 10 oct  6 00:25 pci-0000:00:1d.7-usb-0:3:1.0-scsi-0:0:0:0-part1 -> ../../sdl1
```

Y si lo que quieres es solo el dispositivo en cuestión, el script bash quedaría tal que así:

```
#! /bin/bash

# Busca e imprime los dispositivos de almacenamiento USB

findUSB=$(ls -lh /dev/disk/by-path/ | grep usb | grep part)

foundUSB=${findUSB##*/}

echo $foundUSB
```

El script es rudimentario, y no permite detectar más de un dispositivo usb. Si necesitas que detecte más de un dispositivo, tendrás que modificarlo para que trate la salida de /dev/disk/by-path línea por línea y no en global tal y como lo hace ahora mismo.

Si encuentras una solución mejor, comentalo por el foro porque ya me pica la curiosidad.

----------

## johnlu

¡Gracias por haberte tomado la molestia!

Yo había pensado algo parecido pero usando /dev/disk/by-id/* pero no he podido pararme a elaborarlo.

El caso es que no sé hasta qué punto quedaría bien la integración de un script BASH con un programa C++, pero tendré que verlo detenidamente, que llevo varios días bastante ocupado. Lo digo porque, tu script, por ejemplo, debería ser llamado desde el código C++.

----------

## agdg

Mis conocimientos de programación tienden a 0, en cualquier caso lo que tu quieres hacer se consigue haciendo uso de system.

```
#include <stdlib.h>

main()

{ printf(''Creando carpeta...'');

       system(''mkdir $HOME/tmp'');

}
```

Podrías embutir el script en tu código C, sin embargo sería poco eficiente puesto que cada llamada a system abre una shell independiente; lo cual es mucho más ineficiente que abrir un único shell donde se ejecute el script.

El script bash podría quedar tal que así:

```
#! /bin/bash

# Busca e imprime los dispositivos de almacenamiento USB

if [ $# = 0 ]; then

TMPFILE="./tmp"

else

TMPFILE=$1

fi

ls -lh /dev/disk/by-path/ | grep usb | grep part > $TMPFILE

exec 3<$TMPFILE

while read line <&3

do

foundUSB="$foundUSB "/dev/"${line##*/}"

done

exec 3<&-

echo $foundUSB > $TMPFILE

```

Este script no tiene los problemas que tenía el anterior, es decir, es capaz de detectar todas las partciones de todos los dispositivos de almacenamiento USB conactados. Además el script genera un fichero, por defecto ./tmp, donde almacena las particiones de disco usb encontradas. Si deseas modificar la ruta/nombre de este fichero temporal puedes hacerlo simplemente pasándoselo como comando al invocar el script. Por ejemplo, script.sh /home/user/fichero-temporal

La llamada desde el código C sería

```
system(''script.sh RUTA-FICHERO-TEMPORAL'');
```

Ahora tan solo tendrás que leer, desde C, las particiones desde este fichero temporal, y posteriormente eliminarlo.

En cualquier caso, seguro que en un foro de programación te podrán ayudar bastante más y ofrecerte una solución mejor.

----------

## johnlu

Muchas gracias por la ayuda.

La verdad que para este caso sería mejor consultar en un foro de programación.

De todos modos para ir empezando a tener algo funcional podría ir implementándolo de este modo.

----------

## JotaCE

 *johnlu wrote:*   

> Muchas gracias por la ayuda.
> 
> La verdad que para este caso sería mejor consultar en un foro de programación.

 

Osea que valemos pa pura mami ???

----------

## johnlu

 *JotaCE wrote:*   

> Osea que valemos pa pura mami ???

 

No he dicho eso, ni tampoco era mi intención ni tan siquiera insinuar algo parecido.

En cualquier caso, ¿tienes alguna sugerencia, información o cualquier cosa que pueda ayudar?

----------

## pcmaster

Hola,

El System Rescue CD, que está basado en Gentoo, tiene un script de bash (usb_inst.sh) que te permite instalarlo en un USB, pero sólo en un USB, es decir, no en el disco duro. Si miras el código de ese script, encontrarás una función que por el nombre parece ser la que averigua si un dispositivo es USB o no:

```

# check that device $1 is an USB-stick

is_dev_usb_stick()

{

        curdev="$1"

        

        remfile="/sys/block/${curdev}/removable"

        vendor="$(cat /sys/block/${curdev}/device/vendor 2>/dev/null)"

        model="$(cat /sys/block/${curdev}/device/model 2>/dev/null)"

        if [ -f "${remfile}" ] && cat ${remfile} 2>/dev/null | grep -qF '1' \

                && cat /sys/block/${curdev}/device/uevent 2>/dev/null | grep -qF 'DRIVER=sd'

        then

                return 0

        else

                return 1

        fi

}

```

----------

## johnlu

Gracias pcmaster, mañana entraré en http://www.sysresccd.org e investigaré detalladamente ese script y os contaré si me puede venir bien, que seguramente sí   :Very Happy: 

Ahora mismo es algo tarde, y es hora de que vaya a descansar ya.

----------

## agdg

La proción del script que ha  pegado pcmaster, es una función ( is_dev_usb_stick() ) que devuelve 0 en caso de que se trate de dispositivo de almacenamiento removible; y 1 en caso contrario.

Imagino que esta función será llamada de forma reiterada (en un bucle) para cada uno de los dispositivos encontrados; es decir, debe haber otra parte en el script que le pase los dispositivos sobre los que debe actuar.

Imagino que esa parte debe ser similar a....

```
while /sys/block/

do 

is_dev_usb_stick()

done
```

Si lo hacen usando /sys/block, seguramente será por algo. Así que sera mejor que sigas ese camino.

----------

