[bash] find avec execution en fonction d'un test

Bonjour à tous,

Je voudrais compresser des fichiers avec gzip uniquement s’il ne sont pas déjà compressé.

Pour être plus explicite, le logiciel Blender permet d’enregistrer et lire ces fichiers compressé avec gzip mais en maintenant l’extension *.blend.

Mes fichiers blend étant relativement nombreux et lourds, je souhaite les compresser dans mon circuit de sauvegarde.

J’ai fait le script suivant :

1 #!/bin/bash 2 3 ## déplacement dans le fichier de sauvegarde 4 cd /mnt/SAVE 5 6 ## recherche récursive des fichiers blend et compression gzip 7 find -name \*.blend -exec gzip {} + 8 9 ## recherche récursive des fichier blend.gz précedement créer et renommage en fichier blend 10 find . -name "*.blend.gz" -exec rename -v 's/\.blend.gz$/\.blend/i' {} \;

Le problème est que je peux recompresser des fichiers ayant déjà été compressé.

Je souhaiterais donc tester au préablable les fichiers pour savoir s’il sont déjà compressé au format gzip.

J’imaginais pouvoir remplacer la ligne 7 de mon script par cette ligne :

mais la réponse de “gzip-l” étant du type “gzip: test.blend: not in gzip format” lorsque le fichier n’est pas déjà compressé, les “$0” de ma ligne ne fonctionne évidemment pas.

Auriez-vous une idée ?
Je ne suis pas doué en script, j’ai glané sur le net pour en arriver là tout seul et maintenant je sèche

Merci de vos retours

Bon WE

La piste “magique” :

Faire un :

et lire…
Puis faire un :

et lire…

Puis voir ce que donne la commande “file -bi” ci-dessous:

michel@deb-quad:~$ file -bi Documents/mes_blender/exemple-non-compacté.blend application/octet-stream; charset=binary michel@deb-quad:~$ file -bi Documents/mes_blender/exemple-compacté.blend application/x-gzip; charset=binary

Merci de ton interet MicP,

Pour être sûr, on parle bien de magic : magic — file command’s magic pattern file
et non du paquet magic : magic - VLSI layout editor ?

En tout les cas il va falloir que je regarde à tête reposé car à première vue, je ne sais pas exploiter la réponse “application/gzip; charset=binary” dans mon script de recherche pour qu’il ne compresse pas les fichiers ayant cette réponse.

Merci encore

Oui: je parlais bien de "magic : magic — file command’s magic pattern file"
Je ne suis qu’un autodidacte, donc, je programme pas forcément comme il faut, aussi j’espère que des personnes plus compétentes pourront nous aider pour la deuxième question:
comment exploiter la réponse “application/gzip; charset=binary”.

Je serais tenté d’utiliser simplement cette chaîne de caractère dans une comparaison d’égalité dont le résultat conditionnerait la compression du fichier.
À première vue il faudrait créer une fonction qui va être appelée par le “-exec” de la ligne #7 de ton script.
je vais faire quelques recherches et des tests pour voir si je dis pas trop de bêtises

Pas mieux, voir même moins :slightly_smiling: .

C’est ce à quoi j’avais pensé au départ, mais je ne sais pas intégré des “if” dans la commande find.
Peut-être en effet en appelant un second script avec le exec.

Aujourd’hui j’ai un peu trop de retard à rattraper pour m’y consacrer. Donc désolé de ne pas être plus actif.

Merci encore de ton interet et bonne recherche

EDIT (à ceux qui passeront par là plus tard):
Dans ce post, on peux voir que je me suis tellement concentré sur le problème de test par “file -ib”, que j’en ai oublié de bien contrôler l’action (rename …)
De plus, je n’ai pas pris assez de temps pour me renseigner sur la commande “find”, et j’ai tenté d’utiliser la variable $(FICHIER) là ou un “%h/” aurait été bien plus efficace.
RESULTAT:
l’affichage par “echo” était à première vue correct, mais à première vue seulement…
et l’exécution de la commande “rename” à mis le désordre dans les fichiers à traiter.
TOUJOURS VÉRIFIER ET TOUJOURS FAIRE DES TESTS AVANT DE LANCER SUR LE RÈEL
FIN DE L’EDIT

Et ça, qu’est-ce que ça donne ?
(j’ai n’ai laissé qu’un “echo “${FICHIER}”” pour les tests et commenté la commande qu’il suffira de dé-commenter si tout va bien)

[code]#!/bin/bash

le dossier des sauvegardes

CHEMIN_SAVE="/mnt/SAVE"

(le “” en fin de ligne permet de “couper” la ligne de commande en plusieurs)

rechercher les fichiers “.blend” et créer une liste avec un nom de fichier par ligne ("\n"),

puis renvoyer cette liste par un “pipe” ("|") vers la commande suivante.

find “${CHEMIN_SAVE}” -name *.blend -printf “${CHEMIN_SAVE}/”%f\n | \

lire la liste de lignes créée par “find”

while read FICHIER
do
# Est-ce bien un fichier “.blend” qui n’a pas encore été compacté par “gzip” ?
[[ $( file -ib “${FICHIER}” ) != “application/x-gzip; charset=binary” ]] &&
{
# compresser et renommer le fichier
echo “${FICHIER}”
#gzip “${FICHIER}” && rename -v ‘s/.blend.gz$/.blend/i’ “${FICHIER}”;
};
done;[/code]
EDITxxx:
je viens de tomber sur ça:
softpanorama.org/Tools/Find/ … find.shtml
je crois que je vais y trouver ce qu’il te faut, il ne me reste plus qu’à lire, tester, et assimiler…
A+

Wouah!!
Ça dépasse largement mes compétences

le : echo "${FICHIER}"
Ressort bien la liste récursive des fichier blend sauf ceux déjà compressé.

Par contre quand je décommente la commande, le script compresse uniquement les fichiers blend de la racine, les autres affiche l’erreur : “gzip: /mnt/SAUVEGARDE/test/Exemple/modelisation.blend: No such file or directory”

Et pour ceux de la racine qui sont compressé, la commande “rename” ne semble pas fonctionner, les fichiers reste en .blend.gz

En tout cas merci beaucoup, car déjà vu le retour de la commande echo, je pense que la solution est on ne peux plus proche :041

pour le problème de renommage et de racine, je suis allé un peu vite, et j’aurais dû vérifier un peu mieux ce que je postais.
En fait, il suffisait de remplacer la ligne:
gzip “${FICHIER}” && rename -v ‘s/.blend.gz$/.blend/i’ “${FICHIER}”;
par:
gzip “${FICHIER}” && mv “${FICHIER}.gz” “${FICHIER}”;
(j’ai corrigé cette ligne plus tard après avoir lu le post suivant)

Pour le problème correspondant au message: “gzip: /mnt/SAUVEGARDE/test/Exemple/modelisation.blend: No such file or directory”:
Pourtant, ici : ${CHEMIN_SAVE}/"%f je spécifie bien que le chemin absolu soit transmis, de plus, l’affichage (juste “echo” sans dé-commenter la commande) serait correct.
Il reste la possibilité que le chemin spécifié dans la variable “CHEMIN_SAVE” ne soit pas un chemin absolu, mais comme tu me poste: “gzip: /mnt/SAUVEGARDE/test/Exemple/modelisation.blend: No such file or directory”, je vois bien que le chemin commence à la racine, et du coup, je vois pas du tout ce qui pourrait empêcher “gzip” de faire son travail.

Oups une petite correction :
gzip “${FICHIER}” && mv “${FICHIER}.gz” “${FICHIER}”;

Pour les sous répertoire c’est de ma faute, mon exmeple n’était pas explicite :
En fait pour le fichier “/mnt/SAVE/travail/test.blend"
et pour : CHEMIN_SAVE=”/mnt/SAVE"
le message d’erreur est : gzip: /mnt/SAVE/test.blend: No such file or directory

En fait il ne prend pas en compte le chemin complet et les raccrochent à la racine. Aucun soucis pour ceux qui se trouve effectivement à la racine.

J’ai essayé avec gzip -r mais sans plus. Je pense que $FICHIER devrait contenir l’arborescence complète et dans ce cas, peut-être supprimer $CHEMIN_SAVE.

Pour info, chez moi j’ai remplacé application/x-gzip; charset=binary par application/gzip; charset=binary
C’est ce que me retourne la commande file -bi sur les fichiers concerné

Merci

Désolé pour les erreurs, j’espère que ça n’a pas trop créé de désordre dans tes fichiers, quoique en voyant que tu avais utilisé un sous-dossier nommé “test”, je suppose que tu avais eu la sagesse de faire des essais avant de lancer le script.

Pour le chemin, je comprends mieux ce qui se passe :
Un extrait du man de find :
"%f Nom du fichier, sans aucun nom de répertoire (dernier élément uniquement)."

Toujours dans le man de “find” :
"%h Répertoires en tête du nom de fichier (tout sauf la dernière partie). Si le nom du fichier ne contient aucune barre oblique (NDT : slash) (donc si c’est un fichier du répertoire courant), alors l’option %h rajoutera « . »."

Donc, il faudrait remplacer la ligne:

par:

======================
D’autre part, en faisant un man gzip, j’ai pu me rendre compte qu’il est possible de réduire la dernière ligne de commande, en utilisant l’option “-c”.

-c --stdout --to-stdout Write output on standard output; keep original files unchanged. If there are several input files, the output consists of a sequence of independently compressed members. To obtain better compression, con‐ catenate all input files before compressing them.
En deux mots, on peux rediriger le flux de sortie de gzip vers un fichier en utilisant le caractère ">"
la ligne de commande :

peut donc être remplacée par:

Ça fait toujours un “mv” en moins…
Mais je suis certain qu’il doit être possible de faire mieux, ne serait-ce qu’au sujet des “;” en trop, et de bien d’autres choses que ne ne vois pas.
Ah! si un vrais programmeur pouvais passer par là…

Un grand Merci à toi Micp,
C’est toi qui à fait tout le boulot.

Au final la version qui fonctionne : [code]#!/bin/bash

le dossier des sauvegardes

CHEMIN_SAVE="/tmp"

(le “” en fin de ligne permet de “couper” la ligne de commande en plusieurs)

rechercher les fichiers “.blend” et créer une liste avec un nom de fichier par ligne ("\n"),

puis renvoyer cette liste par un “pipe” ("|") vers la commande suivante.

find “${CHEMIN_SAVE}” -name *.blend -printf %h/%f\n | \

lire la liste de lignes créée par “find”

while read FICHIER
do
# Est-ce bien un fichier “.blend” qui n’a pas encore été compacté par “gzip” ?
[[ $( file -ib “${FICHIER}” ) != “application/gzip; charset=binary” ]] &&
{
# compresser et renommer le fichier
#echo "${FICHIER}"
gzip “${FICHIER}” && mv “${FICHIER}.gz” “${FICHIER}”;
};
done;
[/code]

J’ai conservé la commande de gzip avec le mv, car celle avec gzip -c crée des fichiers vides.
J’ai tenté de remplacégzip -c "${FICHIER}" > "${FICHIER}";pargzip -c "${FICHIER}" >> "${FICHIER}"; mais la commande ne s’arrête pas et Gzip consomme du CPU. Après 2,3 minutes et un CTRL-C, un seul fichier .blend (le premier du repertoire) est malgré tout bel et bien compressé.

En tout cas bravo à toi ça fonctionne impec.
A charge de revanche, si je peux t’aider sur autre chose

Je te remercie beaucoup pour ton message.

Pour la dernière commande, je pense qu’il aurait fallu plutôt utiliser un “pipe” car réécrire sur un fichier qu’on lit n’est pas très bon, même si j’avais pas compris pourquoi ça fonctionnait chez moi, j’avais trouvé la solution bien pratique, mais
gzip “${FICHIER}” && mv “${FICHIER}.gz” "${FICHIER}"
est effectivement bien plus propre.

Oh que oui, j’aurais sûrement bientôt besoin de tes compétences vu que le fait d’avoir redémarré blender m’a donné envie de m’y remettre, mais il y a si longtemps,
il faut juste que je prenne le temps de me remettre dans le bain, et à jour.

En tout cas, ça aura été un plaisir de pouvoir faire ce chemin avec toi, et j’en aurais beaucoup appris sur la commande “find” que je n’utilise pratiquement pas, et d’autres subtilités du bash qu’il me reste à apprendre.

Bonne journée et à bientôt.

Avec plaisir, je commence à me débrouiller avec blender, tu peux me trouver à ce sujet sur http://blenderclan.tuxfamily.org et n’hésite surtout pas par MP.

A la prochaine :023

Le temps de reprendre un peu en main blender qui a beaucoup évolué (ma machine aussi…), de fouiller dans la doc et les tuto, de lire un peu tout ça et de bien définir ce que je veux faire avec en espérant pouvoir rédiger mes questions aussi bien que tu l’a fait ici.
Je vais commencer par suivre le lien que tu m’a transmis.
À bientôt.