Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

traitement de liste (long)

5 réponses
Avatar
françois
Bonjour,



On m'a refilé plusieurs dossier traité avec
l'utilitaire par2 (Parchive parity files), ça vérifie l'intégrité de
fichiers et les répare au cas il serait défectueux (abîmé lors d'un
transfert par exemple), ça marche comme en mode raid, donc il y a une
notion de parité, je n'en sait pas plus mais c'est trés efficace.

donc, l'utilisateur (initiale) crée des fichiers de parité avec la commande

"par2create <dossier>"

ce qui génère dans le dossier en question plusieurs petit fichier du type:

<nom_dossier>.vol00+01.par2
<nom_dossier>.vol01+03.par2
[...]
<nom_dossier>.par2
(c'est ce dernier qui est utilisé pour les vérifications et réparations)

une fois transmis par ftp, ssh ... ou encore aprés gravure
(disque rayé par exemple), l'utilisateur finale n'a plus qu'à
contrôler le dossier avec la commande:

"par2verify <nom_dossier>.par2"

si tous ce passe bien, la commande indique "all files ok",
dans le cas contraire, les fichiers crées précédemment sont utilisé
pour une réparation éventuelle avec la commande

"par2repair <nom_dossier>.par2"

(encore faut-il que les fichiers de parités ne soient pas abîmés, mais
il y redondance donc ... )

voilà pour l'exposé de la commande par2.

Mon problème est le suivant:

vu que je dois vérifier une 60aine de dossiers, je me vois mal taper 60
fois la même commande, donc évidemment j'essaie de concevoir une
commande qui me fera le travaille, à première vu cela parait simple:

1) isoler le fichier <nom_dossier>.par2 de chaque dossier.

2) les traiter un à un avec la commande par2verify (voir par2repair).

3) récupérer les résultats dans un fichier log


Pour le point 1) ça va:

je me place dans le répertoire ou se trouve tous les dossiers puis:


find . -name "*par2" |grep -v ".*\.vol[0-9]*\+[0-9]*"

ce qui me donne en sortie la liste (c'est bien une liste?) de tous les
fichiers <nom_dossier>.par2. ok


Pour le point 2) (je bloque)

je passe en argument la liste obtenu dans une boucle for:

$ for i in `find . -name "*par2" |grep -v ".*\.vol[0-9]*\+[0-9]*"` \
> do par2verify "$i" \
> done

là, le truc part "en vrille", déjà à ce point je ne peut plus continuer
avec un if pour récupérer le résultat, et utiliser "par2repair" le cas
échéant puis "logger" le tout.

J'essaie alors de voir la sortie, en mode pas à pas en utilisant "less"
, je vois que les noms de fichiers sont tronquer à chaque espace
rencontré et donc chaque occurence est passé par "for" à "par2verify"
ce qui le fait planter logiquement, un truc du genre:

pour un nom de fichier "la petite maison" j'ai :

The recovery file does not exist: ./la
The recovery file does not exist: ./petite
The recovery file does not exist: ./maison

J'ai déjà rencontré ce problème, je m'en suis sorti avec
les guillemets pour "$i", mais là, avec ou pas, j'ai la même chose.



Si quelqu'un a une idée, cela m'aiderait.

Merci.

ps: le repertoire ou se trouve les dossiers est stocké sur une
partition ntfs mais bon, ça marche trés bien a la mano ...

ne pas faire attention au précédent poste, il y a quelques erreurs
d'ailleur je le supprime merci.

5 réponses

Avatar
Pascal Bourguignon
françois writes:
[...]
"par2verify <nom_dossier>.par2"
[...]
si tous ce passe bien, la commande indique "all files ok",
[...]
"par2repair <nom_dossier>.par2"
[...]
Mon problème est le suivant:
[...]
1) isoler le fichier <nom_dossier>.par2 de chaque dossier.
2) les traiter un à un avec la commande par2verify (voir par2repair).
3) récupérer les résultats dans un fichier log
[...]
find . -name "*par2" |grep -v ".*.vol[0-9]*+[0-9]*"

ce qui me donne en sortie la liste (c'est bien une liste?) de tous les
fichiers <nom_dossier>.par2. ok


Une liste, c'est un bien grand mot. En shell, on a des chaines, et à
la limites des "tableaux".

Ce que fait find, utilisé comme ça, c'est écrire sur sa sortie
standard le nom des fichiers chacun sur une ligne.


Pour le point 2) (je bloque)

je passe en argument la liste obtenu dans une boucle for:

$ for i in `find . -name "*par2" |grep -v ".*.vol[0-9]*+[0-9]*"`
do par2verify "$i"
done



J'utiliserais plutôt:

find . -name "*par2"
| grep -v ".*.vol[0-9]*+[0-9]*"
| while read i ; do
par2verify "$i"
done

là, le truc part "en vrille", déjà à ce point je ne peut plus continuer
avec un if pour récupérer le résultat, et utiliser "par2repair" le cas
échéant puis "logger" le tout.


par2verify indique "all files ok". Où ? Sur sa sortie standard ou
sur sa sortie erreur ? Est ce que par hasard, elle ne donnerait pas
un status non null lorsque on n'a pas "all files ok" ? Est ce qu'il
n'y aurait pas un status spécifique pour disinguer une erreur avec les
fichiers d'un autre type d'erreur ?

Si "all files ok" <=> status=0 alors on pourrait utiliser:

par2verify "$i" || par2repair "$i"

Sinon, on peut grepper:

par2verify "$i" 2>&1 | grep -q -s 'all files ok' || par2repair "$i"


J'essaie alors de voir la sortie, en mode pas à pas en utilisant "less"
, je vois que les noms de fichiers sont tronquer à chaque espace
rencontré et donc chaque occurence est passé par "for" à "par2verify"
ce qui le fait planter logiquement, un truc du genre:


Oui, c'est normal. C'est pour ça que je préfère utiliser find | while read...

[...]


--
__Pascal Bourguignon__ http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay


Avatar
françois
Pascal Bourguignon wrote:

ce qui me donne en sortie la liste (c'est bien une liste?) de tous les
fichiers <nom_dossier>.par2. ok



Une liste, c'est un bien grand mot. En shell, on a des chaines, et à
la limites des "tableaux".


ok, j'avais un doute ...



Ce que fait find, utilisé comme ça, c'est écrire sur sa sortie
standard le nom des fichiers chacun sur une ligne.




effectivement


Pour le point 2) (je bloque)




J'utiliserais plutôt:

find . -name "*par2"
| grep -v ".*.vol[0-9]*+[0-9]*"
| while read i ; do
par2verify "$i"
done



magnifique, c'est pile ce que je voulais !!
c'est donc grace au "read" qu'il ne découpe pas le nom de fichier ?



là, le truc part "en vrille", déjà à ce point je ne peut plus continuer
avec un if pour récupérer le résultat, et utiliser "par2repair" le cas
échéant puis "logger" le tout.



par2verify indique "all files ok". Où ? Sur sa sortie standard ou
sur sa sortie erreur ?


sur sa sortie standard

Est ce que par hasard, elle ne donnerait pas
un status non null lorsque on n'a pas "all files ok" ?
Est ce qu'il n'y aurait pas un status spécifique pour disinguer une erreur avec les
fichiers d'un autre type d'erreur ?



càd un code de retour ?
non, tout est indiqué sur sa sortie standard, erreur ou pas.
Lorsqu'il y a erreur, il indique le(s) fichier(s) corrompu et le nombre
de blocs qu'il faut pour réparer, et si cela est possible.

Si "all files ok" <=> status=0 alors on pourrait utiliser:

par2verify "$i" || par2repair "$i"



pas possible, enfin je pense

Sinon, on peut grepper:

par2verify "$i" 2>&1 | grep -q -s 'all files ok' || par2repair "$i"



ok, je tente plutôt ça, quoiqu'ici le "2>&1" ne sert pas, car tout est
envoyer sur la sortie standard comme dit plus haut.



J'essaie alors de voir la sortie, en mode pas à pas en utilisant "less"
, je vois que les noms de fichiers sont tronquer à chaque espace
rencontré et donc chaque occurence est passé par "for" à "par2verify"
ce qui le fait planter logiquement, un truc du genre:



Oui, c'est normal. C'est pour ça que je préfère utiliser find | while read...



je prend note !


[...]




Un Grand Merci .


Avatar
Pascal Bourguignon
françois writes:
J'utiliserais plutôt:
find . -name "*par2"
| grep -v ".*.vol[0-9]*+[0-9]*"
| while read i ; do par2verify "$i"
done



magnifique, c'est pile ce que je voulais !!
c'est donc grace au "read" qu'il ne découpe pas le nom de fichier ?


Essaye les commandes suivantes:

(echo 'un, et deux';echo 'trois, et quatre')

echo `echo 'un, et deux';echo 'trois, et quatre'`

(echo 'un, et deux';echo 'trois, et quatre')|while read l;do echo "$l";done

for word in `echo 'un, et deux';echo 'trois, et quatre'`;do echo "$word";done

(IFS=, ;(echo 'un, et deux';echo 'trois, et quatre')|while read g d;do echo "g=$g d=$d";done)

(IFS=, ;for w in `echo 'un, et deux';echo 'trois, et quatre'`;do echo "$w";done)

echo -n "$IFS"|od -a

man bash


Est ce que par hasard, elle ne donnerait pas
un status non null lorsque on n'a pas "all files ok" ? Est ce qu'il
n'y aurait pas un status spécifique pour disinguer une erreur avec
les
fichiers d'un autre type d'erreur ?



càd un code de retour ?
non, tout est indiqué sur sa sortie standard, erreur ou pas.
Lorsqu'il y a erreur, il indique le(s) fichier(s) corrompu et le
nombre de blocs qu'il faut pour réparer, et si cela est possible.

Si "all files ok" <=> status=0 alors on pourrait utiliser:
par2verify "$i" || par2repair "$i"



pas possible, enfin je pense


On peut le vérifier avec:

par2verify bon.par2 && echo bon || echo mauvais
par2verify mauvais.par2 && echo bon || echo mauvais

ou:

par2verify bon.par2 ; echo $?
par2verify mauvais.par2 ; echo $?

Sinon, on peut grepper:
par2verify "$i" 2>&1 | grep -q -s 'all files ok' || par2repair
"$i"



ok, je tente plutôt ça, quoiqu'ici le "2>&1" ne sert pas, car tout est
envoyer sur la sortie standard comme dit plus haut.



--
__Pascal Bourguignon__ http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush


Avatar
françois
Pascal Bourguignon wrote:


Essaye les commandes suivantes:

(echo 'un, et deux';echo 'trois, et quatre')

echo `echo 'un, et deux';echo 'trois, et quatre'`

(echo 'un, et deux';echo 'trois, et quatre')|while read l;do echo "$l";done

for word in `echo 'un, et deux';echo 'trois, et quatre'`;do echo "$word";done



Ah oui pu...naise.

(IFS=, ;(echo 'un, et deux';echo 'trois, et quatre')|while read g d;do echo "g=$g d=$d";done)

(IFS=, ;for w in `echo 'un, et deux';echo 'trois, et quatre'`;do echo "$w";done)


encore plus parlant avec une valeur différente d'IFS !


echo -n "$IFS"|od -a



J'ai pigé
CQFD

man bash



tout à fait d'accord :-) .



Est ce que par hasard, elle ne donnerait pas
un status non null lorsque on n'a pas "all files ok" ? Est ce qu'il
n'y aurait pas un status spécifique pour disinguer une erreur avec
les
fichiers d'un autre type d'erreur ?



càd un code de retour ?
non, tout est indiqué sur sa sortie standard, erreur ou pas.
Lorsqu'il y a erreur, il indique le(s) fichier(s) corrompu et le
nombre de blocs qu'il faut pour réparer, et si cela est possible.





Ok, mais en interne comme tu le dis il y a bien un truc retourner
au shell, ce qui, aprés réflexion, me parait évident, mais bon parfois
ça tourne pas rond...

Si "all files ok" <=> status=0 alors on pourrait utiliser:
par2verify "$i" || par2repair "$i"






tout à fait

pas possible, enfin je pense




laisse tomber je te dit, ça tourne pas rond


On peut le vérifier avec:

par2verify bon.par2 && echo bon || echo mauvais
par2verify mauvais.par2 && echo bon || echo mauvais



ça marche nickel

ou:

par2verify bon.par2 ; echo $?
par2verify mauvais.par2 ; echo $?




idem, pour info retourne 0 en cas de succès et 1 dans le cas contraire

Sinon, on peut grepper:
par2verify "$i" 2>&1 | grep -q -s 'all files ok' || par2repair
"$i"



ok, je tente plutôt ça, quoiqu'ici le "2>&1" ne sert pas, car tout est
envoyer sur la sortie standard comme dit plus haut.



n'importe quoi

Bon je retourne aux bouquins et aux mans :-)

MERCI



Avatar
Pascal Bourguignon
françois writes:
Si "all files ok" <=> status=0 alors on pourrait utiliser:
par2verify "$i" || par2repair "$i"






tout à fait
[...]
On peut le vérifier avec:
par2verify bon.par2 && echo bon || echo mauvais
par2verify mauvais.par2 && echo bon || echo mauvais



ça marche nickel

ou: par2verify bon.par2 ; echo $?
par2verify mauvais.par2 ; echo $?



idem, pour info retourne 0 en cas de succès et 1 dans le cas contraire


Voilà, donc c'est plus simple et plus sûr d'utiliser le status, quand
il est disponible, car les messages peuvent changer d'une version à
l'autre, ou d'un réglage à l'autre du locale...

par2verify "$i" || par2repair "$i"

--
__Pascal Bourguignon__ http://www.informatimago.com/
Wanna go outside.
Oh, no! Help! I got outside!
Let me back inside!