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
où 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.
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 {} ';'
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.