Vous n'êtes pas identifié(e).
Ca marche impec sur les dossiers avec peu de fichiers. Le problème, c'est qu'il y a des dossiers avec un très grand nombre de fichiers (jusqu'à 300'000) et le script échoue sur ces dossiers avec une erreur "argument list too long".
En cherchant un peu, j'ai vu que c'était causé par le $i/*:
It's a kernel limitation on the size of the command line argument. Use a for loop instead.
Origin of problem
This is a system issue, related to execve and ARG_MAX constant. There is plenty of documentation about that (see man execve, debian's wiki).
Basically, the expansion produce a command (with its parameters) that exceeds the ARG_MAX limit. On kernel 2.6.23, the limit was set at 128 kB.
https://stackoverflow.com/questions/112 … v-commands
J'ai donc un peu changé et j'ai mis une deuxième boucle for, avec une commande find:
Ca marche aussi pour les petits répertoires, mais quand j'arrive au gros répertoire de 300'000 fichiers, le script affiche le message
et ne bouge plus.
J'ai cherché sur le net et n'ai rien trouvé sur une "option invalide 4" avec la commande touch...
Si je vais simplement "à la main" dans ce répertoire et fais
j'obtiens à nouveau une erreur
et si je fais
j'obtiens à nouveau
Quelqu'un aurait-il une solution à ce problème?
Dernière modification par vakuy (02-03-2018 16:34:08)
Hors ligne
Hors ligne
Hors ligne
Une idée du pourquoi? J'ai essayé sans la longue variable à la fin, avec un simple 201803031600 comme valeur à touch, ça ne marche pas non plus.
Hors ligne
Je précise que mon script démarre à partir du deuxième répertoire seulement, je n'ai pas réussi à le faire démarrer à partir du premier répertoire
Hors ligne
Hors ligne
Dernière modification par vakuy (02-03-2018 18:51:15)
Hors ligne
Non.
Si tu fais
Non.
Si tu fais
Ok : on encadre systématiquement les chaine de caractères dans des guillemets, c'est une question de bonne pratique.
Je sais pas si ça va corriger le problème, mais ptéte.
je n'ai pas réussi à le faire démarrer à partir du premier répertoire
Initialise $line avec "line=0" pas avec "let line=line+1" (c'est crade en plus, bash initalise bien à 0 mais c'est pas du tout compréhensible de loin tu fais +1 à un truc non initialisé) - ou à la limite fais "let line=0" mais c'est du pareil au même.
A moins que ton problème était ailleurs ?
Hors ligne
Hors ligne
alors que line n'est pas initialisé est incorrecte.
Il vaut mieux directement faire :
Ensuite tu loupes la premiière entrée car dans ta boucle while,
tu incrémentes line avant ta boucle for… il aurait mieux valu
faire :
mais ça reste assez tordu comme code. J'ai d'autres propositions à
faire.
Ta façon de procéder est un peu complexe, je trouve. D'autant qu'il
faut éviter les $(ls -l …) dans des boucle for et while.
Mais prenons les choses dans l'ordre.
Remarque que pour compter le nombre d'entrée dans le répertoire $ENVDOC
il suffit de faire :
Et ensuite puisque tu veux faire une boucle sur entrée avec son numéro
de ligne commençant à 1 (pour sed), il suffit de faire :
On peut même faire la même chose avec une seule boucle for :
Bon on a déjà supprimé une boucle avec un ls -l. Mais ce n'est pas
tout. On peut tous les supprimer et on a pas besoin de la variable
line. Car à quoi sert le
sinon à afficher le nom de l'entrée courante. Bash sait très bien le
faire sans passer par ls -l.
En faisant tout simplement :
Et puisque que tu extrais la date du nom de chaque répertoire,
il n'y a pas pas besoin du « ls -l » (Je le répète, de toute façon ce
n'est pas la bonne manière de procéder pour une boucle).
Et ton code devient le suivant :
On peut encore améliorer, en extrayant une seule fois la date de
chaque répertoire de $ENVDOC, et faisant un touch massif sur tous les
fichiers de ce répertoire.
Ce qui fait qu'en utilisant xargs derrière le find, ça devrait être
incomparablement plus rapide :
Je ne suis pas sûr que ça marchera, à tester sur un répertoire de
test !
Hors ligne
Dernière modification par vakuy (04-03-2018 18:22:30)
Hors ligne
Ca marche impec sur les dossiers avec peu de fichiers. Le problème, c'est qu'il y a des dossiers avec un très grand nombre de fichiers (jusqu'à 300'000) et le script échoue sur ces dossiers avec une erreur "argument list too long".
En cherchant un peu, j'ai vu que c'était causé par le $i/*:It's a kernel limitation on the size of the command line argument. Use a for loop instead.
Origin of problem
This is a system issue, related to execve and ARG_MAX constant. There is plenty of documentation about that (see man execve, debian's wiki).
Basically, the expansion produce a command (with its parameters) that exceeds the ARG_MAX limit. On kernel 2.6.23, the limit was set at 128 kB.
Voilà comment il opère, il lit une liste de chaîne passée sur son
entrée standard, et il donne cette liste à la commande qu'on lui donne
en argument, mais en plus il tient compte de la limitation sur la
taille de ARG_MAX, et il va relancer la commande autant de fois que
nécessaire jusqu'à épuiser les données sur l'entrée standard.
Mais je peux faire un petite amélioration à ce que je t'ai proposé.
Le défaut lorsqu'on utilise find et xargs de cette façon, c'est que
les noms de fichiers vont être séparés par des nouvelles lignes. Pour
être tout à fait général et sûr il vaut mieux utiliser un caractère
nul à la place. Et ceci a été prévu dans find et xargs. D'où ma
nouvelle version :
Le -print0 demande à find de terminer chaque chaîne par un
caractère nul et le -0 dit à xargs que les chaînes données
en entrée sont séparées par des caractères nul (au lieu des nouvelles
lignes par défaut). Le caractère nul (c'est à dire zéro) est le seul caractère avec
le / a être interdit dans un nom de fichier. Voilà pourquoi, c'est plus
sûr de faire comme cela.
En résumé, grâce à xargs on peut opérer sur plusieurs fichier en même temps,
tout en prenant compte de la longueur maximum de la liste d'arguments que l'on peut
donner à une commande.
Dernière modification par enicar (04-03-2018 19:07:21)
Hors ligne
Hors ligne