Shell aide sur mon script - Shell/Batch - Programmation
Marsh Posté le 17-03-2007 à 19:10:50
dd_pak a écrit : J'ai des competences en shell bash mais pas assez pour faire ce script |
Bon, déjà un gros danger à prévoir => si tu fais "ls -ld dossier" tu n'obtiendras pas la taille du dossier dans le sens "taille cumulée de tous ses fichiers" mais tu obtiendras la taille du dossier dans le sens "taille utilisée pour stocker tous les noms des fichiers qui s'y trouvent"
Pour trouver la taille d'un dossier, tu dois utiliser la commande "du -sk dossier"
Ensuite, pour trouver le plus vieux fichier d'un répertoire, tu peux utiliser l'option "-t" de "ls" qui te donne les fichiers classés par date de dernière modif.
Enfin tu peux télécharger mon cours de shell ici http://fr.lang.free.fr/cours/Shell_v2.0.pdf. Tout le shell est expliqué. Tu y trouveras par exemple un script qui affiche une arborescence de façon récursive (un peu à la façon "tree" ) et d'autres exemples qui pourront t'aider pour faire ce devoir.
PS: Ce devoir n'est pas un devoir de débutant et demande quand-même un certain niveau de connaissances en shell. Tu es donc sensé avoir suivi un cours pour acquérir ces connaissances. Donc ne dis pas que t'as pas les compétences...
Marsh Posté le 20-03-2007 à 11:12:57
Code :
|
Mon problème es que sur la deuxième boucle, le test fichier ou dossier n'est jamais vraie ?
et j'ai pas d'idée comment recuperé l'extension du fichier?
merci
Marsh Posté le 20-03-2007 à 12:57:15
dd_pak a écrit :
|
Bon, à ta première boucle tu fais un "find |while read" => ok - Je ne sais pas si t'as pris cette idée chez-moi (et donc si t'as compris le principe) ou si tu connaissais déjà l'astuce.
Pourquoi, dans ta seconde boucle, tu ne fais pas pareil ? Style "find -type f |xargs ls -ltr | while read file" ???
Petite remarque en passant : La commande "find" peut recevoir une commande qu'elle appliquera automatiquement sur les fichiers qu'elle trouve. Autrement dit, tu peux remplacer "find -type f |xargs ls -ltr" par "find -type f -exec ls -ltr {} \;"
Ensuite, je ne comprends pas trop ce que tu cherches quand tu fais "if test $dossier/$file == -f" car si la variable "$file" récupère une ligne du "ls" (au fait, t'as oublié de sauter la première ligne du "ls" qui indique "total: xxx" ) alors il n'y aura jamais "-f" ou "-d". Si c'est un fichier normal il y aura "-" suivi des droits "rwxrwxrwx", si c'est un répertoire, il y aura "d" suivi des droits. Donc il te faudra extraire le premier caractère de "$file" et comparer ce premier caractère à "-" ou à "d" mais sûrement pas "-f" ni "-d".
De toute façon, c'est une méthode bien compliquée pour déterminer le type du fichier alors que t'as "test -d". Ah, ça y est, j'ai compris. Tu as cru que dans la commande "test" il fallait mettre "test fichier = -d". Non, l'option "-d" ou "-f" sont des options de la commande "test" donc il faut les mettre avant
=> test -f "$dossier/$file"
=> test -d "$dossier/$file"
Bien entendu, il faut que "$file" ne récupère que le nom du fichier et pas les informations au format "long" donc faut enlever l'option "-l" du "ls"...
Comment récupérer une extension ? Un extension est une chaîne qui suit un ".". Donc tu peux utiliser la commande "cut" en coupant sur le ".". Exemple:
nom="toto.doc"
base=`echo $nom |cut -f1 -d.` => base="toto"
ext=`echo $nom |cut -f2 -d.` => ext="doc"
Maintenant, si le nom possède plusieurs extensions, style "toto.tar.gz", alors ça devient plus compliqué et ça dépend de ta façon de voir. Si tu considères que l'extension est "tar.gz" alors ma méthode marche encore ; si tu considères que c'est "gz" alors ça devient plus compliqué (faut compter les "." puis ne prendre que le dernier) et si tu veux récupérer et isoler chaque extension ("tar", "gz" ) alors il faut faire une boucle.
Petites remarques en pasant:
Marsh Posté le 20-03-2007 à 14:59:01
Code :
|
Pour la taille, merci mais je me doute que c'est approximatif, je connais cette règle
Pour le test --d et -f, j'ai trouvé il faut un espace derrière sinon ca ne marche pas
Pour l'extension je dirais .tar.gz => c'est un gz
Donc il faut compter le nombre de point pour le cut mais je n'y arrive pas, il me renvoie 0 ou 1 mais pas 2?
Je te remercie pour ton aide, oui je me suis inspriré de tes conseils, je code mais la c'est mon premier script shell alors j'ai un peu de mal
merci @+
Marsh Posté le 20-03-2007 à 17:07:43
dd_pak a écrit :
|
Ben si tu regardes bien le "cut", je demande le "-f2" c.a.d. le champ n° 2 (sous-entendu "séparé du champ "1" par un "." ) en ayant présumé que le nom n'avait que 2 champs.
Maintenant, si le nom a plusieurs "." non connus à l'avance, il y a plusieurs solutions mais à mon avis, la plus simple est de filtrer le nom par un "awk"
nom="toto.tar.gz"
ext=`echo $nom |awk -F. '{print $NF}' ` => ext="gz"
Explication: chaque ligne traitée par "awk" contient dans sa variable "NF" le nombre de champs de la ligne en question (le séparateur de champs étant indiqué par le "-F" donc ce sera "." ). Donc en affichant la variable "$NF" (qui est une variable spécifique au langage "awk" ), j'affiche le texte correspondant au dernier champ et ce, quel que soit le nombre de champs du flux entrant.
Marsh Posté le 21-03-2007 à 09:51:44
Merci mon script et enfin fini, merci pour ton aide je crois pas que j'aurais reussi tout seul
Je suis consient que l'on peut l'ameliorer mais pour le moment ca me suffit
Voici le code ca peut toujours servir à quelq'un.
Encore merci pour ton aide et tes explications
Code :
|
Marsh Posté le 21-03-2007 à 12:53:28
dd_pak a écrit : Merci mon script et enfin fini, merci pour ton aide je crois pas que j'aurais reussi tout seul |
It's my job...
dd_pak a écrit :
|
Petit danger: les variables en majuscules sont réservées au système. Imagine que, sans le savoir, tu aies utilisé la variable "PATH" ou "HOME" ??? Ben c'est pareil. Tu ne sais pas si le système n'utilise pas, pour lui, "DATE". Evidemment c'est improbable mais c'est pour le principe. Et puis un nom en minuscule est souvent plus lisible...
Sinon amélioration rapide:
# Affiche la date pour le log |
dd_pak a écrit :
|
Petites remarques mineures
1) en général, une fonction est écrite en premier car on considère qu'on pourrait avoir à s'en servir de partout. Imagines que t'aies à t'en servir lors du renommage des fichiers zarbi, ben tu pourrais pas.
2) je ne comprends pas à quoi sert la variable "supp" dans ta fonction. Tu testes si elle est à "1" mais sinon tu ne fais rien. Autant ne pas appeler "old" si ce n'est pas utile. Par ailleurs, si vraiment ta fonction "old" devait recevoir un paramètre à "1", autant le lui passer directement comme paramètre justement et non pas par le biais d'une variable venue du dehors. Si dans ton code principale il te prend l'envie de modifier le nom "supp" en autre chose, faudra reporter cette modif dans la fonction !!!
3) je ne comprends pas trop pourquoi tu mets l'option "-l" dans ton "ls" ce qui t'oblige à mettre l'option "C" sinon t'aurais un affichage au format long. Autant faire un "ls -atr" ou, au pire, si t'es pas sûr de toi, un "ls -atr1" qui force l'affichage à n'être que sur une seule colonne...
4) une fonction ne travaille pas sur une copie des variables mais sur les variables elle-mêmes ça c'est très dangereux. Dans ta fonction "old" tu utilises les variables "$dossier" et "$supp" et "$file". Tu utilises aussi ces mêmes variables dans ton code principal.
Imagines que t'aies un truc de ce style
for $file in truc |
Ben le passe par "old" a écrasé le "$file" par celui qui est dans "old". Et ton traitement suivant plante.
Pour éviter ce danger, toujours mettre ton code de fonction entre parenthèses - Ca ne change pas l'accès aux valeurs des variables mais ce ne sont que des copies et les originaux ne sont pas modifiés
old(){ |
PS: Les accolades dans les corps des structures for/if/while ne sont pas obligatoires. Les mots clefs "then/else/fi/do/done" permettent au shell de se repérer dans le code. Sinon j'aime bien ton script. On sent que t'es à l'aise dans la syntaxe shell et t'as bien pigé la récursivité (ta fonction "old" qui s'appelle elle-même). Le reste viendra avec le temps...
Marsh Posté le 21-03-2007 à 14:30:48
Citation : On sent que t'es à l'aise dans la syntaxe shell |
Merci encore, je corrige tout les petites remarques, sinon non je suis pas à l'aise c'est pour ca que tu m'a aidé, c'est mon premier script...
mais je code en perl,php,sql,javascript,html donc ca aide
Marsh Posté le 16-03-2007 à 15:07:13
J'ai des competences en shell bash mais pas assez pour faire ce script
2 paramètres a renseigner en debut de script
- le dossier
- taille du dossier max en mega
Si le dossier a une taille > taille max --> on efface LE plus vieux fichier(il peut avoir des sous dossiers, sur plusieur niveaux),
si un sous dossiers est vide le supprimer.
J'espère être clair
Merci @+ franck
Message édité par dd_pak le 20-03-2007 à 11:10:05