2009-10-21 8 views
10

Estoy construyendo una pequeña herramienta que descargará archivos usando wget, leyendo las URL de diferentes archivos. La misma URL puede estar presente en diferentes archivos; la URL puede estar presente en un archivo varias veces. Sería ineficiente descargar una página varias veces (cada vez que su URL se encuentre en la lista).Cómo calcular un hash para una cadena (url) en bash para wget caching

Por lo tanto, el enfoque simple es guardar el archivo descargado y ordenar a wget que no lo descargue nuevamente si ya está allí.

Eso sería muy sencillo; sin embargo, las URL son muy largas (muchos parámetros GET) y, por lo tanto, no se pueden utilizar como tales para los nombres de archivo (wget da el error "No se puede escribir en ... [] nombre de archivo demasiado tiempo").

Por lo tanto, necesito cambiar el nombre de los archivos descargados. Pero para que el mecanismo de almacenamiento en caché funcione, el esquema de cambio de nombre debe implementar "one url < => one name": si una url determinada puede tener varios nombres, el almacenamiento en caché no funciona (es decir, si simplemente numere los archivos en el orden se encuentran, no dejaré que wget identifique qué URL ya se han descargado).

El esquema más simple cambio de nombre sería calcular un hash MD5 del nombre de archivo (y no del propio archivo, que es lo que hace md5sum); eso aseguraría que el nombre del archivo sea único y que una url dada tenga siempre el mismo nombre.

Es posible hacer esto en Perl, etc., pero ¿se puede hacer directamente en bash o utilizando una utilidad del sistema (RedHat)?

Respuesta

24

Parece que quiere la utilidad del sistema md5sum.

URLMD5=`/bin/echo $URL | /usr/bin/md5sum | /bin/cut -f1 -d" "` 

Si desea crear sólo el hash en el nombre del archivo, se puede conseguir que la rapidez con la sed:

FILENAME=`echo $URL | /bin/sed -e 's#.*/##'` 
URLMD5=`/bin/echo $FILENAME | /usr/bin/md5sum | /bin/cut -f1 -d" "` 
+0

Bueno muchas gracias por la respuesta rápida; ¡No me había dado cuenta de que simplemente podía usar md5sum de esta manera! Sin embargo, no entiendo lo que dice sobre el 'nombre de archivo': cuando se calcula la clave md5, ¿todavía no hay nombres de archivo ...? – Bambax

+0

@bambax: Epsilon Prime se refiere a la parte de nombre de archivo de la URL, por ejemplo: "index.html". El comando 'sed' elimina todo, incluso la última barra inclinada. –

+0

@Dennis: Ok, gracias; pero en ese caso, ciertamente no quiero usar solo el nombre del archivo como parte de la URL, ya que diferentes conjuntos de parámetros GET deberían dar como resultado que se almacenen/recuperen diferentes archivos. – Bambax

1

versiones más recientes de Bash proporcionan una matriz asociativa, así como una matriz indexada. Algo como esto podría funcionar para usted:

declare -A myarray 
myarray["url1"]="url1_content" 
myarray["url2"]="" 

if [ ! -z ${myarray["url1"]} ] ; then 
    echo "Cached"; 
fi 

wget normalmente cambiará el nombre de los archivos con un filename.html.1, 0.2, etc., por lo que podría utilizar la matriz asociativa para almacenar una lista de la que se tiene se ha descargado y cuál era el nombre real del archivo.

8

No tengo el representante para comentar la respuesta, pero hay una aclaración a la respuesta de Epsilon Prime: de forma predeterminada, echo imprimirá una nueva línea al final del texto. Si desea que las sumas MD5 para que coincida con lo que va a ser generado por cualquier otra herramienta (por ejemplo, php, MD5 de Java, etc.) es necesario llamar a

echo -n "$url" 

que suprimir la nueva línea.

+0

Eso es algo realmente extraño de tener que hacer. Me alegra que ahora lo sepa. – buildsucceeded

3

Otras opciones en mi caja de Ubuntu (precisa):

  • echo -n $STRING | sha512sum
  • echo -n $STRING | sha256sum
  • echo -n $STRING | sha224sum
  • echo -n $STRING | sha384sum
  • echo -n $STRING | sha1sum
  • echo -n $STRING | shasum

Otras opciones en mi Mac:

  • echo -n $STRING | shasum -a 512
  • echo -n $STRING | shasum -a 256
  • etc.
Cuestiones relacionadas