/* outils récursifs de répertoire A besoin de la v37. Afficheur universel de répertoire. Appelé sans arguments, et tapant juste "d", il liste le répertoire courant. Arguments: DIR,REC/S,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,FULL/S,NOANSI/S, TARGET/K,DO/K/F DIR spécifie un chemin optionnel au répertoire que vous voulez lister. il peut contenir des caractères génériques standards comme #?~[]%() etc. REC spécifie que les sous-répertoire doivent être listés récursivement. COL où n=1..3, par défaut, D liste les répertoires en 3 colonnes. le tout bien mignon et compact. spécifie 1 ou 2 si vous voulez. SIZE reporte la taille de chaque répertoire lors de l'affichage. Notez que combiné avec REC, ça donne le taille de tout le répertoire et des sous répertoires. NOSORT par défaut, les répertoires sont triés avant l'affichage. Mettez cette option hors service avec NOSORT. NOFILES affiche juste les répertoires. NODIRS affiche juste les fichiers. FULL met le chemin entier au lieu des fichiers juste. NOANSI n'utilise pas l'affichage ansi lors de l'impression. TARGET spécifie le répertoire destination pour l'utilisation avec DO. le répertoire doit se terminer pas "/" ou ":" DO spécifie la ligne de commande pour la génération automatique des scripts. Notez que celui utilise toute la fin de la ligne. Je doit dire quelquechose à dire sur les caractèristiques des scripts: ils permettent de faire des taches répétitives sur des répertoires, ou des arbres- répertoires. Les utilitaires éxistant qui vous permettent ce type de tache, ne sont pas assez souple ; D vous permet d'utiliser le mot REC en combinaison avec les scripts, accepte des extensions variables: utilisez .o si le nom original est .s, et le chemin de destination: les fichiers créés par l'opération sont placés dans un autre répertoire qui peut être une image d'un autre arbre-répertoire. Les commandes 'makedir' sont insérés si la destination est vide. Les formats suivant peuvent être utilisé dansla ligne de commande: %s est le fichier (chemin et nom) %f est le fichier SANS extension %r est le fichier sans extension, mais un remplacé par (utile si permet un fichier de sortie) %> ou %< %>> etc. prévients le shell de croire que ">" is une redirection pour D, au lieu de Un exemple complexe: Vous voulez avoir une référence complète ascii du répertoire emodules:, récursivement, et avec un fichier .txt créé comme une structure répertoire image quelque part. 1> D >ram:script emodules: REC TARGET=t:mods/ DO showmodule %>%r.txt %s 1> execute ram:script le fera pour vous. POur tous les fichiers du type "emodules:exec/io.m" D fera uneligne du style: "showmodule >t:mods/exec/io.txt emodules:exec/io.m" autres exemples: D >mydirlist dh0: COL=2 SIZE REC NOANSI D docs: DO type >prt: %s D asm: TARGET=obj: DO genam %s -o%r.o D emodules: REC TARGET=ram: DO showmodule %>%r.txt %s BUGS: y en a plus. AMéLIORATIONS PAR RAPPORT AU VIEUX "D" - beaucoup plus rapide - récursif - calcule la taille des fichiers d'arbres d'un répertoire entier - une, deux, trois colonnes - caractères génériques (? * #?) - meilleur tri, et plus rapide - meilleur code : gère les répertoire de toutes les tailles - un tas d'option grace au standard readargs() - génération puissant de script - utilise des gestionnaires d'exception imbriqués pour pister les appels MatchEnd() lors d'un CtrlC ou un erreur soudaine. */ OPT OSVERSION=37 CONST MAXPATH=250 ENUM ER_NONE,ER_BADARGS,ER_MEM,ER_UTIL,ER_ITARG,ER_COML ENUM ARG_DIR,ARG_REC,ARG_COL,ARG_SIZE,ARG_NOSORT,ARG_NOFILES, ARG_NODIRS,ARG_FULL,ARG_NOANSI,ARG_TARGET,ARG_COMMAND,NUMARGS MODULE 'dos/dosasl', 'dos/dos', 'utility' RAISE ER_MEM IF New()=NIL, /* fixe les exceptions habituelles: */ ER_MEM IF String()=NIL, /* chaque appel à ces fonction seront */ ERROR_BREAK IF CtrlC()=TRUE /* automatiquement vérifié vis à vis de */ /* NIL et l'exception ER_MEM est levée */ DEF dir,command,target, recf=FALSE,col=3,comf=FALSE,sizef=FALSE,sortf=TRUE,filesf=TRUE, fullf=FALSE,ansif=TRUE,dirsf=TRUE,dirw[100]:STRING, rdargs=NIL,work[250]:STRING,work2[250]:STRING,dirno=0, prtab[25]:LIST,prcopy[25]:LIST,workdir[250]:STRING PROC main() HANDLE DEF args[NUMARGS]:LIST,templ,x,lock,fib:fileinfoblock,s IF (utilitybase:=OpenLibrary('utility.library',37))=NIL THEN Raise(ER_UTIL) FOR x:=0 TO NUMARGS-1 DO args[x]:=0 templ:='DIR,REC/S,COL/K/N,SIZE/S,NOSORT/S,NOFILES/S,NODIRS/S,' + 'FULL/S,NOANSI/S,TARGET/K,DO/K/F' rdargs:=ReadArgs(templ,args,NIL) IF rdargs=NIL THEN Raise(ER_BADARGS) /* initialise les drapeaux */ IF args[ARG_SIZE] THEN sizef:=TRUE /* des arguments de la commande */ IF args[ARG_COL] THEN col:=Long(args[ARG_COL]) IF args[ARG_NOSORT] THEN sortf:=FALSE IF args[ARG_NOANSI] THEN ansif:=FALSE IF args[ARG_NOFILES] THEN filesf:=FALSE IF args[ARG_NODIRS] THEN dirsf:=FALSE IF args[ARG_REC] THEN recf:=TRUE IF args[ARG_FULL] THEN fullf:=TRUE target:=args[ARG_TARGET] command:=args[ARG_COMMAND] IF command THEN comf:=TRUE IF (col<>1) AND (col<>2) THEN col:=3 IF target x:=target+StrLen(target)-1 IF (x":") AND (x[]<>"/")) THEN Raise(ER_ITARG) ENDIF IF comf sortf:=FALSE /* lit et convertis la commande pour les scripts */ col:=1 filesf:=FALSE dirsf:=FALSE IF command[]=0 THEN Raise(ER_COML) s:=command WHILE x:=s[]++ IF x="%" x:=s[] SELECT x CASE "s"; ListAdd(prtab,[1],1) /* %s = chemin entier */ CASE "f"; ListAdd(prtab,NEW [work],1); s[]:="s" /* %f = work */ CASE "r"; ListAdd(prtab,NEW [work2],1); s[]:="s" /* %r = work2 */ DEFAULT; s[-1]:=" " ENDSELECT ENDIF ENDWHILE ENDIF dir:=args[ARG_DIR] IF dir THEN StrCopy(dirw,dir,ALL) lock:=Lock(dirw,-2) IF lock /* si oui, le rép prob., sinon car. générique */ IF Examine(lock,fib) AND (fib.direntrytype>0) AddPart(dirw,'#?',100) ENDIF UnLock(lock) ENDIF recdir(dirw) Raise(ER_NONE) EXCEPT IF rdargs THEN FreeArgs(rdargs) IF utilitybase THEN CloseLibrary(utilitybase) SELECT exception CASE ER_BADARGS; WriteF('Mauvais Arguments pour D!\n') CASE ER_MEM; WriteF('Pas de mémoire!\n') CASE ER_COML; WriteF('Pas de ligne de commande spécifié\n') CASE ER_ITARG; WriteF('Cible illégale\n') CASE ER_UTIL; WriteF('Nepeut pas ouvrir l''"utility.library" v37\n') CASE ERROR_BREAK; WriteF('Arrêt de D par l'utilisateur\n') CASE ERROR_BUFFER_OVERFLOW; WriteF('Erreur interne\n') DEFAULT; PrintFault(exception,'Dos Error') ENDSELECT ENDPROC PROC recdir(dirr) HANDLE DEF er,i:PTR TO fileinfoblock,size=0,anchor=NIL:PTR TO anchorpath,fullpath, flist=NIL,first,entries=0,sortdone,next,nnext,prev,ascii,x,y,flist2=NIL, esc1,esc2,ds:PTR TO LONG,isfirst=0 anchor:=New(SIZEOF anchorpath+MAXPATH) anchor.breakbits:=4096 anchor.strlen:=MAXPATH-1 esc1:=IF ansif THEN '\e[1;32m' ELSE '' esc2:=IF ansif THEN '\e[0;31m' ELSE '' ds:=['\s\l\s[50]\s ','\l\s[47] \r\d[8]','\s\l\s[30]\s ','\l\s[27] \r\d[8]','\s\l\s[19]\s ','\l\s[17] \r\d[7]'] er:=MatchFirst(dirr,anchor) /* collecte les chaines */ WHILE er=0 fullpath:=anchor+SIZEOF anchorpath i:=anchor.info ascii:=IF fullf THEN fullpath ELSE i.filename IF i.direntrytype>0 THEN StringF(work,ds[col-1*2],esc1,ascii,esc2) ELSE StringF(work,ds[col-1*2+1],ascii,i.size) IF IF i.direntrytype>0 THEN dirsf ELSE filesf first:=String(EstrLen(work)) StrCopy(first,work,ALL) flist:=Link(first,flist) INC entries ENDIF IF i.direntrytype<0 THEN size:=size+i.size IF (i.direntrytype<0) AND comf /* éxécute la ligne de cmd */ ListCopy(prcopy,prtab,ALL) IF comf THEN MapList({x},prcopy,prcopy,`IF x=1 THEN fullpath ELSE x) StrCopy(work,fullpath,ALL) x:=InStr(work,'.',0) IF x<>-1 THEN SetStr(work,x) /* trouve f% */ IF target StrCopy(work2,target,ALL) x:=work; y:=dirw /* was dirr */ WHILE x[]++=y[]++ DO NOP DEC x StrAdd(work2,x,ALL) /* trouve r% */ ELSE StrCopy(work2,work,ALL) ENDIF IF isfirst++=0 StrCopy(workdir,work2,ALL) /* regarde si makedir est nécessaire */ SetStr(workdir,PathPart(work2)-work2) x:=Lock(workdir,-2) IF x THEN UnLock(x) ELSE WriteF('makedir \s\n',workdir) ENDIF Flush(stdout); VfPrintf(stdout,command,prcopy); Flush(stdout) WriteF('\n') ENDIF IF recf AND (i.direntrytype>0) /* fait la récursion(=tail) */ x:=StrLen(fullpath) IF x+5ERROR_NO_MORE_ENTRIES THEN Raise(er) MatchEnd(anchor) Dispose(anchor) anchor:=NIL flist:=Link(String(1),flist) IF entries>2 AND sortf REPEAT sortdone:=TRUE /* tri de la liste de rép */ prev:=first:=flist WHILE first:=Next(first) IF next:=Next(first) IF Stricmp(first,next)>0 nnext:=Next(next) Link(prev,first:=Link(next,Link(first,nnext))) sortdone:=FALSE ENDIF ENDIF CtrlC() prev:=first ENDWHILE UNTIL sortdone ENDIF IF col>1 /* met lalist de rép en colonne */ x:=entries/col IF x*col=0) StrCopy(work,first,ALL) IF next StrAdd(work,' ',1) StrAdd(work,next,ALL) IF nnext StrAdd(work,' ',1) StrAdd(work,nnext,ALL) ENDIF ENDIF ascii:=String(EstrLen(work)) StrCopy(ascii,work,ALL) Link(prev,prev:=ascii) first:=Next(first) IF next THEN next:=Next(next) IF nnext THEN nnext:=Next(nnext) ENDWHILE DisposeLink(flist) flist:=flist2 ENDIF IF comf=FALSE /* affiche le rép */ IF dirno THEN WriteF('\n') WriteF(IF ansif THEN '\e[1mRépertoire de: "\s"\e[0m\n' ELSE 'Répertoire de: "\s"\n',dirr) ENDIF first:=flist WHILE first:=Next(first) WriteF('\s\n',first) CtrlC() ENDWHILE IF sizef THEN WriteF('BYTE SIZE: \d\n',size) DisposeLink(flist) INC dirno EXCEPT /* gestionnaire d'exception! */ IF anchor THEN MatchEnd(anchor) Raise(exception) /* Comme ça on peut appeler _tous_ les gestionnaires dans la récursion */ ENDPROC size /* et donc appeler MatchEnd() sur tousles 'anchors' */