Bonjour, ô forum.
Dans mon post précédent, je me demandais comment tester si un objet présent dans un répertoire est un fichier ou un répertoire, sachant que j'écrivais un programme en bash.
Plus exactement, les deux tests que je veux écrire sont:
"si ce n'est pas un répertoire....."
"si ce n'est pas un fichier....."
En cherchant, j'ai fini pas trouver qu'il faut utiliser S_ISDIR et S_ISREG qui sont des macros décrites ici : http://www.linux-kheops.com/doc/man/manfr/man-html-0.9/man2/stat.2.(...)
Sauriez-vous comment il faut s"en servir?
Merci.
Forum Programmation.shell utilisation de S_ISDIR et S_ISREG
7
sept.
2005
# Ben, man bash ...
Posté par Obsidian . Évalué à 2.
for i in *
do
[ -d $i ] || echo "$i n'est pas un répertoire"
[ -f $i ] || echo "$i n'est pas un fichier régulier"
done
Mais il me semble également avoir vu ce genre d'expression dans ton précédent script. Qu'est-ce qui ne fonctionne pas ?
[^] # Re: Ben, man bash ...
Posté par Obsidian . Évalué à 2.
Les macros en question sont simplement là pour contrôler l'état de tel ou tel flag, sans que tu aies besoin de connaitre ceux-ci en particulier.
[^] # Re: Ben, man bash ...
Posté par RobertRyan . Évalué à 2.
En fait, dans mon script précédent, j'avais fait ceci :
cd /home
for a in * ; do
# ignorer tous les objets qui ne sont pas des répertoires
if [ ! -d "$a" ] ; then
continue
fi
if [ "$a" = \* ] ; then
break
fi
cd "/home/$a"
for b in * ; do
# ignorer tous les objets qui ne sont pas des fichiers
if [ ! -e "$b" ] ; then
continue
fi
if [ "$b" = \* ] ; then
continue
fi
mais les tests sur les fichiers et les repertoires faisaient que le programme ne fonctionnaient pas bien. Je les ai donc supprimés.
Sinon, ta solution est peut-être juste, mais je ne la comprends pas bien. Et en quoi est-elle différente de la mienne?
[^] # Re: Ben, man bash ...
Posté par netsurfeur . Évalué à 3.
Manifestement, ton script n'est pas complet : il manque les fins de boucles for. En plus: - le cd "/home/$a" à l'intérieur de la boucle change ton répertoire courant, il faut que tu reviennes au répertoire parent en fin de boucle. - les tests avec des continue ne simplifient pas la compréhension du script: ll vaut mieux inverser le test. - les tests [ $a = \* ] et [ $b = \* ] sont inutiles, voire faux: - soit $a vaut * parce que le répertoire /home est vide et le test [ -d "$a" ] le traite correctement - soit $a vaut * parce /home contient un répertoire nommé * (ça peut arriver, les noms de fichiers peuvent contenir des métacaractères) et ton script va l'ignorer alors qu'il aurait dû le traiter. - si tu veux tester que $b est un fichier le test devrait être -f et non -e qui ne teste que l'existence et qui est vrai aussi pour un répertoire.cd /home for a in * ; do # traiter uniquement les répertoires if [ -d "$a" ] ; then cd "/home/$a" for b in * ; do # traiter uniquement les fichiers if [ -f "$b" ] ; then # TRAITEMENT fi done fi cd .. # retour au repertoire /home done[^] # Re: Ben, man bash ...
Posté par Obsidian . Évalué à 2.
Bon la solution est quelque part dans la banquise du message précédent :
[ -e "$a" ] teste l'existence d'un « objet » sur ton filesystem.
[ -f "$a" ] teste si cette entrée est un fichier régulier ou pas.
Bon courage.
[^] # Script achevé
Posté par RobertRyan . Évalué à 1.
Ayé! Enfin! Je vous remercie tous pour vos contributions. En particulier la tienne, netsurfeur. Je suis épaté par la rapidité de vos réactions et la qualité de vos réponses. Si si! Donc j'ai terminé mon script et je le poste ici, sait-on jamais, ça pourrait servir à d'autres. Je rappelle à quoi il sert : Les employés d'une entreprise d'audit créés, chaque fois qu'une entreprise est auditée, un fichier contenant leur rapport sous /home/[le rep de l'auditeur] (ex : Jacques dépose ses rapports dans /home/Jacques). Le rapport est de la forme [nom de l'entreprise].extension (ex : Renault.doc). Le programme déplace les rapports des auditeurs et les place sous /Rapports/[nom de l'entreprise] (ex : le rapport renault.doc de Jacques sera placé sous /Rapports/Renault). Eventuellement, si l'entreprise est auditée pour la première fois (et qu'il n'y a donc pas encore de répertoire à son nom sous /Rapports), le programme créé un répertoire au nom de l'entreprise. Le premier rapport déposé prendra alors le nom, par exemple, Sony.001.doc. Si l'entreprise a été auditée plusieurs fois, le programme renomme le rapports en le déplaçant. Ainsi, le 2nd rapport sur Renault s'appellera Renault.002.doc, le 3ième, Renault.003.doc, etc... N'hésitez pas à me demandez des précisions si je n'ai pas été assez clair. ________________________________________________________________________________ #! /bin/bash # Le programme suivant prend en compte un nombre illimité d'auditeurs et jusqu'à 999 rapports. # Les rapports sont traités quelque soit leur extension. # Le nom des rapports peut contenir n'importe quel signe y compris des espaces. # Le nom des rapports classés est de la forme 'société.001.ext'. # Le fait d'ajouter un point entre le nom de la société et le numéro permet de prendre # en compte la présence éventuelle de chiffres dans le nom de la société. # Variables : # a = répertoires des auditeurs sous /home # b = rapports non classés # c = nom de la société auditée # d = numéro du dernier rapport classé # e = extension du rapport cd "/home/Linux/Profils/" for a in * ; do # traiter uniquement les répertoires if [ -d "$a" ] ; then cd "/home/Linux/Profils/$a" for b in * ; do # traiter uniquement les fichiers if [ -f "$b" ] ; then # on extrait du nom du rapport le nom de la société # c'est à dire tout ce qui est avant le dernier point c=${b%*.*} # on récupère l'extension du rapport à classer # c'est à dire tout ce qui est après le dernier point e=.${b##*.} # un répertoire au nom de la société existe-t-il déjà? cd "/home/Linux/Rapports" if [ -d "$c" ] ; then cd "$c" # on extrait de la liste le dernier fichier ajouté # (celui dont le nombre est le plus grand) d=$(ls -1 | tail -1) # on retire au fichier son extension d=${d%*.*} # on extrait son numéro d=${d##*.} # on supprime les zéros non significatifs d=$(echo $d | sed 's/^0*//') # on incrémente ce numéro de 1 d=$(($d + 1)) # on lui accolle 2 '0' d=00$d # on extrait les 3 premiers chiffres (à partir de la droite) # \([0-9][0-9][0-9]\) et \1 : motif conservant les 3 chiffres de droite d=$(echo $d | sed 's/^0*\([0-9][0-9][0-9]\)/\1/g') # on déplace enfin le rapport du répertoire de l'auditeur # dans le répertoire de la société en le renommant mv "/home/Linux/Profils/$a/$b" "/home/Linux/Rapports/$c/$c"."$d$e" else # on crée un répertoire au nom de la société mkdir "/home/Linux/Rapports/$c" # on y déplace alors le rapport en lui attribuant le numéro '001' mv "/home/Linux/Profils/$a/$b" "/home/Linux/Rapports/$c/$c".001"$e" fi fi # le prog se trouvait alors dans /home/Linux/Rapports, # il faut qu'il revienne dans le répertoire de l'auditeur # pour traiter les rapports restant cd "/home/Linux/Profils/$a" done fi # le prog se trouvait alors dans le répertoire d'un auditeur, # il faut qu'il revienne sous /home pour traiter les répertoires # des autres auditeurs cd "/home/Linux/Profils/" done[^] # Re: Script achevé
Posté par -=[ silmaril ]=- (site web personnel) . Évalué à 1.
# Variables :
# a = répertoires des auditeurs sous /home
# b = rapports non classés
# c = nom de la société auditée
# d = numéro du dernier rapport classé
# e = extension du rapport
Aurait tu oublie la premiere maxime de la programmation utile:
"utiliser des noms de variables significatifs"
Autre chose:
tu a du cd "/home/Linux/Profils/" partout dans ton script, typiquement
une variable aurait ete tres utile au cas ou un changement du repertoire
de base arriverait.
Derniere chose:
Les shells utilisents des alias pour permettrent aux utilisateurs
de ne pas s'encombrer a retapper tout le temps les memes arguments
mais dans un script il est bon de passer outres ceux ci pour eviter un
maximum de comportement incoherents.
De plus tout les unix non pas forcement les memes emplacements
pour les commandes il est donc conseiller de creer des variables
pour toutes les commandes utilisées.
Ah et puis les cd dans un script c'est pas tres propre.
----------------------------------------------
#! /bin/bash
# Commandes
LS=/bin/ls
MV=/bin/mv
SED=/bin/sed
BASENAME=/usr/bin/basename
TAIL=/usr/bin/tail
MKDIR=/bin/mkdir
# Variables :
profils="/home/Linux/Profils"
rapports="/home/Linux/Rapports"
for auditeur in $profils/* ; do
# traiter uniquement les répertoires
if [ -d "$auditeur" ] ; then
for doc in $auditeur/* ; do
# traiter uniquement les fichiers
if [ -f "$doc" ] ; then
base=`$BASENAME $doc`
# on extrait du nom du rapport le nom de la société
# c'est à dire tout ce qui est avant le dernier point
societe=${base%*.*}
# on récupère l'extension du rapport à classer
# c'est à dire tout ce qui est après le dernier point
ext=.${base##*.}
# un répertoire au nom de la société existe-t-il déjà?
if [ -d "$rapports/$societe" ] ; then
# on extrait de la liste le numero du dernier fichier ajouté
# (celui dont le nombre est le plus grand)
d=$($LS -1 "$rapports/$societe" | $TAIL -1 | sed 's/*\.\([0-9]+\)\.*/\1/g')
# on incrémente ce numéro de 1
# on lui accolle 2 '0'
d=00$(($d + 1))
# on extrait les 3 premiers chiffres (à partir de la droite)
d=$(echo $d | sed 's/^0*\([0-9]\{3\}\)/\1/g')
# on déplace enfin le rapport du répertoire de l'auditeur
# dans le répertoire de la société en le renommant
$MV "$doc" $rapports/$societe/$societe.$d$ext"
else
# on crée un répertoire au nom de la société
$MKDIR "$rapports/$societe"
# on y déplace alors le rapport en lui attribuant le numéro '001'
$MV "$doc" "$rapports/$societe/$societe.001$ext"
fi
fi
done
fi
done
[^] # Re: Script achevé
Posté par netsurfeur . Évalué à 2.
Tout à fait d'accord
Là aussi, d'accord.
D'ailleurs le script initial n'avait qu'un seul cd en absolu; les autres étaient relatifs. Il y avait donc moins besoin d'utiliser une variable pour le répertoire de base.
Pas d'accord du tout !
Les emplacements peuvent être différents d'un unix à l'autre mais la variable PATH est là pour résoudre ce problème !
Tu comptes éditer tous tes scripts un par un pour changer les chemins absolus des commandes le jour où tu migreras sur un autre unix ?
[^] # Re: Script achevé
Posté par -=[ silmaril ]=- (site web personnel) . Évalué à 1.
Oui la variable PATH permet de s'affranchir de ce genre d'ennuis
mais pas du probleme des alias. Une solution peut etre de mixer
les deux choses en utilisant:
SED=`which sed`
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.