Ver la versión completa : Otros Lenguajes Bash para comparar y renombrar ficheros
Esto del bash no es lo mio.
Quiero hacer un script que recorra un directorio, comprima todos los archivos .bin a un par de formatos distintos y renombre a .pak el fichero mas pequeño.
Creo que las variables name78, name77 y pack no se crean bien, si ponía su valor al final de la parte de compresión funcionaba bien. Ademas que si hago un echo $name78 no imprime nada.
Gracias.
#!/bin/bash
for file in $(find . -name "*.bin" -type f);
do
# nombres terminados en .l78, .l77 y .pak
name78 = $(dirname $file)"/"$(basename $file .bin)".l78"
name77 = $(dirname $file)"/"$(basename $file .bin)".l77"
pak = $(dirname $file)"/"$(basename $file .bin)".pak"
# comprime
lz78 p $file $name78
lz77 p $file $name77
size78 = $wc -c < $name78
size77 = $wc -c < $name77
# renombre a pak el mas pequeño
if [[ "$size78" -lt "$size77" ]]; then
mv $name78 $pak
else
mv $name77 $pak
fi
done
Los dos problemas que veo a bote pronto:
- Al asignar variables el operador "=" no puede ir entre espacios. Variable, operador y valor han de ir juntos.
- Al tomar el tamaño de los ficheros te olvidaste de los paréntesis de la sustitución de comandos. Es decir, tendría que ser, por ejemplo:
size78=$(wc -c < $name78)
Corrigiendo eso, el script debería de funcionar para los ficheros y directorios cuyos nombres no contengan espacios. Si hay espacios en los nombres habría que hacerle algunas modificaciones. Por cierto, ¿de dónde salen los comandos lz78 y lz79?
----
El tema de los espacios...
Dado que el espacio es el separador de campos por defecto, si el resultado de una sustitución puede contener espacios hay que ponerla entre comillas para que el resultado sea un único argumento y no varios. Ejemplo:
$ echo hola > "un fichero.txt"
$ FILE="un fichero.txt"
$ cat $FILE
cat: un: No such file or directory
cat: fichero.txt: No such file or directory
$ cat "$FILE"
hola
$
Pero eso no va funcionar con la sustitución del 'for', dado que si la pones entre comillas vas a tener un único argumento formado por el nombre de todos los ficheros. Una solución clásica es hacer una iteración por líneas, en la que cada línea es el nombre de un fichero... Usando una tubería se lee cada línea del listado generado por 'find' y se procesa. Y para generar los nombres de ficheros con la extensión cambiada de forma más "fácil" se puede usar uno de los tipos de expansión de parámetros de bash. Entiendo que los comandos lz78 y lz77 no eliminan el fichero original al comprimirlo.
#!/bin/bash
find . -name "*.bin" -type f |
while read file; do
# nombres terminados en .l78, .l77 y .pak
name78=${file%.bin}.l78
name77=${file%.bin}.l77
pak=${file%.bin}.pak
# comprime
lz78 p "$file" "$name78"
lz77 p "$file" "$name77"
size78=$(wc -c < "$name78")
size77=$(wc -c < "$name77")
# renombre a pak el mas pequeño
if [[ "$size78" -lt "$size77" ]]; then
mv "$name78" "$pak"
else
mv "$name77" "$pak"
fi
done
Por cierto, ¿de dónde salen los comandos lz78 y lz77?
De aqui
http://s390174849.online.de/ray.tscc.de/code.htm
Luego miro el resto, ahora estoy en modo weekend.
Ah, OK. Era simple curiosidad. Es que me extrañaba un poco porque esos comandos no me sonaban de nada y vi que en Debian al menos no se encontraban en ningún paquete. Y por otro lado, las utilidades clásicas de compresión (gzip y el viejo compress) ya están basadas en esos algoritmos.
Por cierto, volviendo al script, di por hecho que los ficheros que te interesan están repartidos por un árbol de directorios que cuelga del directorio en el que ejecutas el script, que para eso es útil la búsqueda con 'find'. Porque si no, si están todos en ese mismo directorio, llega con hacer 'for file in *.bin', que es más simple y funciona en todos los casos.
Si, es para comprimir los gráficos que hay en una carpeta y dentro de esta hay varios directorios con lo niveles, etc.
La ventaja es que el código para descomprimir es mínimo, ademas de que lo necesito en ensamblador del 68000
Gracias
Ya funciona, lo "raro" es que el 99% de las veces el lz77 comprime mas que el lz78. Así que casi podría comprimir siempre con el mismo, pero vamos ya que esta hecho mejor así y ahorro algunos bytes.
Pues no sé... Según la Wikipedia (https://en.wikipedia.org/wiki/LZ77_and_LZ78) parece que ambos algoritmos son equivalentes:
They are both theoretically dictionary coders. LZ77 maintains a sliding window during compression. This was later shown to be equivalent to the explicit dictionary constructed by LZ78—however, they are only equivalent when the entire data is intended to be decompressed.
Gzip y compress implementan los algoritmos Deflate y LZW, los cuales a su vez están basados en LZ77 y LZ78 respectivamente. Gzip comprime bastante más que compress aunque no creo que esto sea directamente extrapolable a LZ77 y LZ78. Gzip es la utilidad de compresión que siempre se ha usado en Linux en lugar de compress (que es la estándar en Unix, estándar POSIX de hecho), aunque esto tiene que ver más con el hecho de que LZW estaba patentado.
Ya, digo que es raro porque si miras el código de descompresión el lz77 es muchísimo mas simple XD.
Tengo que probar el nrv2e que al parecer va bastante bien.
http://www.oberhumer.com/opensource/ucl/
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.