Extracción de archivos .gz contenidos en una carpeta

13

Tengo una carpeta que contiene aproximadamente 320116 archivos .pdb.gz. Quiero descomprimirlos a todos. Si uso gunzip * .gz me da un error, es decir, la lista de argumentos es demasiado larga. La carpeta es de aproximadamente 2 GB. Por favor dame una sugerencia apropiada.

Lily Sharpton
fuente
Si tendrá que trabajar en esta estructura de directorio a largo plazo, divida este directorio en muchos. Por ejemplo, según la hora de modificación de los archivos o el nombre de los archivos.
dan
Sí, tengo que trabajar a largo plazo. se han extraído ahora. Quiero subdividirlos y clasificarlos en tres carpetas según sus nombres. ¿Hay un script de shell para hacerlo?
Lily Sharpton
Le sugiero que busque preguntas similares allí. Si no encuentra uno para satisfacer sus necesidades, haga su propia nueva pregunta.
dan

Respuestas:

26
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +proporcionará gunzipmuchos pero no demasiados nombres de archivo en su línea de comando. Esto es más eficiente que el -exec gunzip {} \;que inicia un nuevo gunzipproceso para todos y cada uno de los archivos.

John1024
fuente
3
¡Uno findmenos gunzip!
dan
2
Tenga en cuenta que el "+" es un GNUism y, por lo tanto, no funcionará en sistemas que no sean GNU como * BSD.
Restablecer Monica - M. Schröder
3
Las versiones posteriores de BSD findpermiten la notación "+". Consulte, por ejemplo, la findpágina del manual para BSD 10.1 . También se aplica a OS X (10.9 y posterior al menos, tal vez antes).
plasma
7

Siempre que obtenga errores de "lista de argumentos demasiado larga", puede solucionarlo invocando el comando deseado varias veces, cada vez con un subconjunto de los argumentos que desea usar. xargses una herramienta que te ayuda a hacerlo automáticamente.

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip
Celada
fuente
¿No tiene esto la misma ineficiencia que, por -execdir gunzip "{}" \;ejemplo, xargs invocará gunzip por separado para cada archivo? Esa es mi lectura de la página man.
Gogoud
55
No, xargsrellenará tantos nombres de archivos como quepan en la gunziplínea de comando. ¡Intentalo! echo a b c d e f | xargs echosolo se invoca echouna vez con los 6 argumentos para que vea una línea de salida (comando bastante inútil para ejecutar, sin embargo !!!!), mientras que si obliga xargsa proporcionar solo 3 argumentos por invocación del comando usando echo a b c d e f | xargs -n 3 echo, obtendrá 2 líneas de salida .
Celada
44
Otra ventaja de usar xargses que, con la -Popción, puede ejecutar múltiples gunzipprocesos en paralelo, lo que (dependiendo de los parámetros exactos de su sistema) puede ir más rápido.
psmears
gracias por el puntero a -P@psmears. ¡Ahora también aprendí algo!
Celada
1

Creo que esto debería funcionar, pasa la ruta / nombre de cada archivo individualmente a gunzip para su procesamiento:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;
gogoud
fuente
1
Eso ejecutará gunzip una vez por archivo. Vea la respuesta de John1024 para una forma ligeramente diferente que evita esa ineficiencia.
Celada
@ Celada Esto fue deliberado; Mi preocupación era que usar + podría volver a generar un mensaje de error debido a la sobrecarga de gunzip. Si el método de John1024 funciona, es técnicamente más eficiente, pero el mío debería funcionar si el suyo no funciona.
Gogoud
1
findcon +y xargsestán expresamente diseñados con exactamente ese problema en mente. Siempre proporcionarán tantos argumentos como puedan, sin exceder el límite del sistema operativo. Porque, por cierto, es un límite del sistema operativo, nada que ver gunzip.
Celada
1
@Celada ok, gracias por esa información, así que presumiblemente con '+' gunzip podría ser invocado más de una vez, ¿pero menos de 320,000 veces?
Gogoud
1
correcto.
Celada
1

Intenta de esta manera:

find . -name '*.gz' -exec gunzip {} \;
jherran
fuente
3
Eso se ejecutará gunzipuna vez por archivo. Vea la respuesta de John1024 para una forma ligeramente diferente que evita esa ineficiencia.
Celada
Asegúrese de escapar del * in * .gz ...
user253751
1

Si tiene una máquina multinúcleo, probablemente verá que el uso gunzipno va a maximizar las capacidades de su máquina. Para eso necesitarías ejecutar múltiples gunzips en paralelo. Hacer un seguimiento de qué se hace en qué terminal a mano es engorroso, pero puede hacerlo fácilmente con GNU paralelo:

find . -name "*.gz" | parallel -X gunzip {}
Anthon
fuente
1
¿No fallará eso porque la lista de argumentos paralleles demasiado larga?
user253751
@immibis Sí, olvidé el problema original, actualizaré mi publicación
Anthon
¿No seguirá fallando porque la lista de argumentos findes demasiado larga?
user253751
1
Sí, pero está pasando todos los nombres de archivo en findla línea de comando.
user253751
Parece que este no es un buen día para responder preguntas, olvidé citar el argumento a-name
Anthon
-1

No es necesario usarlo findpara esto, ya que no mencionó subcarpetas. Lo que debes hacer es:

for f in *.gz;do gunzip $f;done
Tolga Ozses
fuente
44
Usted no necesita findsi no quiere desovar 320116 gunzipprocesos, al igual que lo hace este bucle.
John WH Smith