web-dev-qa-db-fra.com

renommer par lots les fichiers Zip en fonction des noms de fichiers contenus

J'ai un répertoire avec 15000 fichiers Zip. J'aimerais renommer tous les fichiers qui, une fois décompressés, contiennent un fichier de la forme

YYYYMMDD_IPC.csv

YYYYMMDD se trouve être une date, mais aux fins de ce problème, toute chaîne de 8 chiffres exactement. Ensuite, le fichier Zip lui-même doit être renommé en

YYYYMMDD_IPC.Zip.

Je suis allé aussi loin que la ligne de commande suivante, mais je ne sais pas comment capturer le YYYYMMDD à partir du fichier contenu à utiliser pour renommer les fichiers Zip:

find . -iname '*.Zip' | while read file; do unzip -l "$file" | grep -q -P '\d{8}_IPC.csv' && echo $file; done 2>&- 

Merci pour la lecture.

2
user2926302
find . -iname '*.Zip' -exec bash -c 'name=$(unzip -qql "$1"  '*_IPC.csv' | grep -oE '[[:digit:]]{8}_IPC.csv' | head -n1); [ "$name" ] && mv "$1" "${name%csv}Zip"' none {} ';'

Comment ça fonctionne

Cette commande a la forme:

find . -iname '*.Zip' -exec bash -c '...' none {} ';'

Cela recherche le fichier .Zip dans le répertoire actuel et tous les sous-répertoires qu'il contient. Pour chacun de ces fichiers, la commande bash entre guillemets simples est exécutée. Le nom du fichier trouvé est fourni à l'argument un, $1, à la commande bash. Dans notre cas, la commande bash a deux parties. Le premier extrait le nom du fichier csv et l’enregistre dans la variable bash name:

name=$(unzip -qql "$1"  '*_IPC.csv' | grep -oE '[[:digit:]]{8}_IPC.csv' | head -n1)

Ce qui précède utilise substitution de commande: la commande à l'intérieur de $(...) est exécutée et sa sortie standard est capturée. Dans ce cas, on l'assigne à la variable name. La commande unzip -qql "$1" '*_IPC.csv' extrait silencieusement tous les noms de fichier du fichier Zip correspondant au glob *_IPC.csv. Nous n'avons pas besoin de nous limiter au glob *_IPC.csv, mais si le fichier Zip contient de nombreux fichiers, cela peut accélérer les choses.

La commande grep, rep -oE '[[:digit:]]{8}_IPC.csv' ne sélectionne en outre que les noms commençant par 8 chiffres. La commande head -n1 sélectionne le premier nom de ce type trouvé. S'il n'y avait qu'un seul nom de ce type, head -n1 ne serait pas nécessaire. Mais garder head pourrait accélérer les choses car le pipeline se terminerait après le premier match.

La deuxième partie teste que nous avons réussi à obtenir un name non vide et, le cas échéant, à renommer le fichier Zip:

[ "$name" ] && mv "$1" "${name%csv}Zip"

Ce qui précède utilise suppression du suffixe pour changer le nom du fichier csv en un nom de fichier Zip. ${name%csv} renvoie $name après avoir supprimé le suffixe csv. ${name%csv}Zip ajoute un suffixe Zip.

4
John1024