Page 1 sur 1
[..] Lister dossier puis fichier
Posté : jeu. 14 mars 2013 11:09
par jcaspar
B
onjour à tous !
Je souhaiterais lister dossiers et les fichiers présents dans chaque dossier..
Le code ci dessous permet de lister les fichiers ou dossier ... Pourriez vous svp
m'expliquer comment faire pour lister les dossiers puis les fichiers...
Je pense qu'il faudrait utiliser une boucle for imbriquée ....
for (i=0; to 100; i++){
for (j=0; to 100; j++)
}
Mais comment indiquer à Autoit qu'il s'agit d'un fichier ou d'un dossier ?
Je vous remercie d'avance pour vos conseils

...
Code : Tout sélectionner
#include <File.au3>
#include <Array.au3>
local $FileList = _FileListToArray("T:\Dossier")
local $sFile="test.txt"
If @error = 1 Then
MsgBox(0, "", "Pas de dossier trouvé.")
Exit
EndIf
If @error = 4 Then
MsgBox(0, "", "Aucun fichier trouvé.")
Exit
EndIf
_ArrayDisplay($FileList, "$FileList")
_FileWriteFromArray($sFile, $FileList, 1)
Re: [..] Lister dossier puis fichier
Posté : jeu. 14 mars 2013 12:52
par lesolutionneur
Je n'ai pas trop le temps de répondre au reste mais voici un élément de réponse pour ceci:
Mais comment indiquer à Autoit qu'il s'agit d'un fichier ou d'un dossier ?
Code : Tout sélectionner
$sPath = "C:\dossier\"
Local $szDrive, $szDir, $szFName, $szExt
_PathSplit($sPath, $szDrive, $szDir, $szFName, $szExt)
If $szFName = "" AND $szExt= "" Then
;On a un dossier
Else
;On a un fichier
EndIf
Sinon, on peut faire autrement mais c'est pas du code très propre:
Code : Tout sélectionner
#include <Array.au3>
#include <File.au3>
Func _FileInFolderListToArray2D($sPath)
$aFolder = _FileListToArray($sPath, "*", 2) ;On ne retourne que les dossiers
Dim $aFile[$aFolder[0]+1] ;On crée un tableau ayant la bonne taille
For $i=1 To $aFolder[0]
$aFile[$i] = _FileListToArray($sPath & $aFolder[$i], "*", 1) ;On retourne les fichiers
Next
_ArrayConcatenate($aFolder, $aFile)
Return $aFolder
EndFunc
Comme ça, tu as un dossier par ligne, colonne 1 de $aFolder (la première ligne contenant le nombre de dossiers)
Et 1 array à la colonne 2 par ligne. (la deuxième ligne contenant le nombre de fichiers)
Tu peux l'utiliser comme ça:
Code : Tout sélectionner
#include <Array.au3>
#include <File.au3>
$aFolder = _FileInFolderListToArray2D("C:\dossier\")
_ArrayDisplay($aFolder[1][1]) ;Affiche les fichiers présents dans le dossier de chemin relatif $aFolder[1][0]
Bonne chance

Re: [..] Lister dossier puis fichier
Posté : jeu. 14 mars 2013 14:33
par mikell
Tu peux aussi utiliser une des nombreuses variantes récursives de _FileListToArray, quitte à rajouter un peu de code
http://www.autoitscript.fr/forum/viewto ... f=21&t=479► Afficher le texte
Code : Tout sélectionner
#Include <Array.au3>
$path = "C:\Program Files\AutoIt3\Examples\GUI"
$res = _FileListToArrayEx($path, "*", 1, 2)
Dim $array[$res[0]+1][2]
For $i = 1 to $res[0]
$array[$i][1] = StringRegExpReplace($res[$i], '.+\\(.+)', "$1")
$array[$i][0] = StringReplace($res[$i], $array[$i][1], "")
Next
_ArraySort($array)
_Arraydisplay($array)
;;#Include "_FileListToArrayEx.au3"
Func _FileListToArrayEx($sPath, $sFilter = "*", $iFlag = 0, $sSDir = 0)
Local $hSearch, $sFile, $sFileList, $sDelim = "|", $sSDirFTMP = $sFilter
$sPath = StringRegExpReplace($sPath, "[\\/]+\z", "") & "\" ; ensure single trailing backslash
If Not FileExists($sPath) Then Return SetError(1, 1, "")
If StringRegExp($sFilter, "[\\/:><]|(?s)\A\s*\z") Then Return SetError(2, 2, "")
If Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then Return SetError(3, 3, "")
$hSearch = FileFindFirstFile($sPath & "*")
If @error Then Return SetError(4, 4, "")
Local $hWSearch = $hSearch, $hWSTMP = $hSearch, $SearchWD, $FPath = StringRegExpReplace(StringRegExpReplace($sSDir, '[^2]+', ""), "2+", StringRegExpReplace($sPath, '\\', "\\\\")), $sSDirF[3] = [0, StringReplace($sSDirFTMP, "*", ""), "(?i)(" & StringRegExpReplace(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace("|" & $sSDirFTMP & "|", '\|\h*\|[\|\h]*', "\|"), '[\^\$\(\)\+\[\]\{\}\,\.\=]', "\\$0"), "\|([^\*])", "\|^$1"), "([^\*])\|", "$1\$\|"), '\*', ".*"), '^\||\|$', "") & ")"]
While 1
$sFile = FileFindNextFile($hWSearch)
If @error Then
If $hWSearch = $hSearch Then ExitLoop
FileClose($hWSearch)
$hWSearch -= 1
$SearchWD = StringLeft($SearchWD, StringInStr(StringTrimRight($SearchWD, 1), "\", 1, -1))
ElseIf $sSDir Then
$sSDirF[0] = @extended
If ($iFlag + $sSDirF[0] <> 2) Then
If $sSDirF[1] Then
If StringRegExp($sFile, $sSDirF[2]) Then $sFileList &= $sDelim & $FPath & $SearchWD & $sFile
Else
$sFileList &= $sDelim & $FPath & $SearchWD & $sFile
EndIf
EndIf
If Not $sSDirF[0] Then ContinueLoop
$hWSTMP = FileFindFirstFile($sPath & $SearchWD & $sFile & "\*")
If $hWSTMP = -1 Then ContinueLoop
$hWSearch = $hWSTMP
$SearchWD &= $sFile & "\"
Else
If ($iFlag + @extended = 2) Or StringRegExp($sFile, $sSDirF[2]) = 0 Then ContinueLoop
$sFileList &= $sDelim & $sFile
EndIf
WEnd
FileClose($hSearch)
If Not $sFileList Then Return SetError(4, 4, "")
Return StringSplit(StringTrimLeft($sFileList, 1), "|")
EndFunc ;==>_FileListToArrayEx
Re: [..] Lister dossier puis fichier
Posté : jeu. 14 mars 2013 14:55
par jguinch
@Mikell
StringRegExpReplace($sPath, '\\', "\\\\")), $sSDirF[3] = [0, StringReplace($sSDirFTMP, "*", ""), "(?i)(" & StringRegExpReplace(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace(StringRegExpReplace("|" & $sSDirFTMP & "|", '\|\h*\|[\|\h]*', "\|"), '[\^\$\(\)\+\[\]\{\}\,\.\=]', "\\$0"), "\|([^\*])", "\|^$1"), "([^\*])\|", "$1\$\|"), '\*', ".*"), '^\||\|$', "") & ")"]
Ca pique les yeux là !!

Re: [..] Lister dossier puis fichier
Posté : jeu. 14 mars 2013 15:12
par mikell
Je suis absolument d'accord
Mais là c'est pas moi, c'est le code original de la fonction _FileListToArrayEx ^^
Re: [..] Lister dossier puis fichier
Posté : jeu. 14 mars 2013 19:07
par lesolutionneur
Euh attends, ton code est encore plus sale que le mien !

Re: [..] Lister dossier puis fichier
Posté : dim. 17 mars 2013 10:31
par GaRydelaMer
Bonsoir
plus propre utilise un objet : "Scripting.FileSystemObject"
Code : Tout sélectionner
#include <Array.au3>
Local $Path = @ScriptDir
Local $oFSO = ObjCreate("Scripting.FileSystemObject"), $sTemp, $Array
If $oFSO.FolderExists($Path) Then
Local $oFolder = $oFSO.GetFolder($Path)
; Lister les sous-dossiers
For $oSubFolder In $oFolder.SubFolders
$sTemp &= $oSubFolder.Name & "\|"
Next
; Lister les fichiers
For $oFile In $oFolder.Files
$sTemp &= $oFile.Name & "|"
Next
EndIf
$oFSO = 0
$Array = StringSplit(StringTrimRight($sTemp, 1), "|")
_ArrayDisplay($Array)
Re: [..] Lister dossier puis fichier
Posté : dim. 17 mars 2013 11:04
par mikell
Sympa le FileSystemObject mais je crois que tu as oublié le principe de son script
jcaspar a écrit :Je souhaiterais lister dossiers et les fichiers présents dans chaque dossier..
En l'état ton script retourne le même résultat qu'un _FileListToArray avec flag 0
Re: [..] Lister dossier puis fichier
Posté : dim. 17 mars 2013 14:57
par GaRydelaMer
Oupss pas vu non plus, mais c'est pareil, moi j'ai nue fonction qui contient ce code en reccursif.
C’était d’ailleurs une discutions pour FileListeToArrayEx() qu'elle solution adopter pour choisir la plus rapide.
Dans SON cas j'utilise effectivement une variante de la fonction que tu as mentionné: _RecFileListToArray() de Melba23.
Re: [..] Lister dossier puis fichier
Posté : dim. 17 mars 2013 17:56
par mikell
Bah tu sais, moi bête et discipliné j'écoute ceux qui savent
Mais j'aimerais bien voir ta fonction récursive à base de FileSystemObject
Re: [..] Lister dossier puis fichier
Posté : lun. 18 mars 2013 04:24
par GaRydelaMer
Bonjour
je me suis amusé à faire une fonction récursive, en fait y'a 2 versions, une avec un tableau classique en 2D l'autre avec un recordset.
J'ai fait la version RecordSet, pour trier facilement le résultat, les dossier en 1er et les noms de fichier classé aussi.
Bien sur on peut après imaginer ajouter un pattern pour afficher que les dossier et/ou les fichiers qu'on veux, limiter la récursion c'est à dire la profondeur des sous dossier etc..
L'autre avantage de la version RecordSet c'est que l'on pourra facilement Filtrer les résultats après
$oRs.Filter = "Type = 'File' And Name Like '*.au3*'" par exemple
Coté performance, je viens de tester la version RecordSet et 3 fois plus rapide sur un dossier qui contient: 9 365 Fichier, 891 Dossiers
Sans le trie
Version RecordSet (10256 rows) en ms: 7522.32655709834
Version Array (10256 rows) en ms: 20128.9287917255
Avec le trie
Version RecordSet (10256 rows) en ms: 7964.32368746228
Version Array (10256 rows) en ms: 21278.4703115633
Le résultat final tu peux avoir un tableau 2d avec (Type = Folder ou File):
0|Type|Name|Path complet
n|
► Afficher le texte
Code : Tout sélectionner
#include <Array.au3>
Global Const $adInteger = 3
Global Const $adVarChar = 200
Local $Timer, $Path = @ScriptDir
$Timer = TimerInit()
Local $oRs = Folders_Files_RecordSet($Path)
ConsoleWrite("Version RecordSet (" & $oRs.RecordCount & " rows) en ms: " & TimerDiff($Timer) & @LF)
Local $aAr = $oRs.GetRows()
_ArrayDisplay($aAr, "Liste des fichier RS: " & $oRs.RecordCount & " rows", -1, 0, "", "|", "iRow|Type|Name|Path")
Func Folders_Files_RecordSet($Path, $iReturn = 0)
Local $oFSO = ObjCreate("Scripting.FileSystemObject")
If Not $oFSO.FolderExists($Path) Then Return SetError(1, 1, "")
; on initialise le RecordSet pour la sortie version RecordSet
Local $oRs = ObjCreate("ADODB.Recordset")
$oRs.Fields.Append("Type", $adVarChar, 255)
$oRs.Fields.Append("Name", $adVarChar, 255)
$oRs.Fields.Append("Path", $adVarChar, 255)
$oRs.Open
Local $oFolder = $oFSO.GetFolder($Path)
Switch $iReturn
Case 2 ; Folders only
__Rec_Folders_Files_RecordSet($oRs, $oFolder, True, False)
Case 1 ; Files only
__Rec_Folders_Files_RecordSet($oRs, $oFolder, False, True)
Case Else ; Both
__Rec_Folders_Files_RecordSet($oRs, $oFolder)
EndSwitch
$oFSO = 0
; Si on trie pas se repositionner à la 1ère ligne du RecordSet
;~ $oRs.MoveFirst
; on fait le trie du RecordSet
$oRs.Sort = "Type Desc, Path, Name"
Return $oRs ; Le RecordSet lui même
EndFunc
Func __Rec_Folders_Files_RecordSet(ByRef $oRs, ByRef $oFolder, $Folders = True, $Files = True)
; Parcours des dossiers
For $oSubFolder In $oFolder.SubFolders
If $Folders Then
Local $aNames[3] = ["Type", "Name", "Path"]
Local $aValue[3] = ["Folder", $oSubFolder.Name, _
$oSubFolder.ParentFolder.Path]
$oRs.AddNew($aNames, $aValue)
EndIf
__Rec_Folders_Files_RecordSet($oRs, $oSubFolder, $Folders, $Files)
Next
; Parcours des fichiers
If $Files Then
For $oFile In $oFolder.Files
Local $aNames[3] = ["Type", "Name", "Path"]
Local $aValue[3] = ["File", $oFile.Name, _
$oFile.ParentFolder.Path]
$oRs.AddNew($aNames, $aValue)
Next
EndIf
EndFunc
$Timer = TimerInit()
Local $aAr = Folders_Files_Array__2D($Path)
ConsoleWrite("Version Array (" & $aAr[0][0] & " rows) en ms: " & TimerDiff($Timer) & @LF)
_ArrayDisplay($aAr, "Liste des fichier RS: " & $aAr[0][0] & " rows", -1, 0, "", "|", "iRow|Type|Name|Path")
Func Folders_Files_Array__2D($Path, $iReturn = 0)
Local $oFSO = ObjCreate("Scripting.FileSystemObject")
If Not $oFSO.FolderExists($Path) Then Return SetError(1, 1, "")
; on Initialise le Tableau pour la sortie version Array
Local $aListe[1][3] = [[0, "", $Path]]
Local $oFolder = $oFSO.GetFolder($Path)
Switch $iReturn
Case 2 ; Folders only
__Rec_Folders_Files_Array__2D($aListe, $oFolder, True, False)
Case 1 ; Files only
__Rec_Folders_Files_Array__2D($aListe, $oFolder, False, True)
Case Else ; Both
__Rec_Folders_Files_Array__2D($aListe, $oFolder)
EndSwitch
$oFSO = 0
; on fait un trie simple du tableau, et on l'affiche on enlèvera ces lignes ici c'est pour la démo
_ArraySort($aListe, 1, 1, 0, 0)
Return $aListe ; Tableau créer par la fonction
EndFunc
Func __Rec_Folders_Files_Array__2D(ByRef $aAr, ByRef $oFolder, $Folders = True, $Files = True)
If $Folders Then ReDim $aAr[UBound($aAr) + $oFolder.SubFolders.Count][4]
; Parcours des dossiers
For $oSubFolder In $oFolder.SubFolders
If $Folders Then
$aAr[0][0] += 1
$aAr[$aAr[0][0]][0] = "Folder"
$aAr[$aAr[0][0]][1] = $oSubFolder.Name
$aAr[$aAr[0][0]][2] = $oSubFolder.ParentFolder.Path
EndIf
__Rec_Folders_Files_Array__2D($aAr, $oSubFolder, $Folders, $Files)
Next
; Parcours des fichiers
If $Files Then
ReDim $aAr[UBound($aAr) + $oFolder.Files.Count][4]
For $oFile In $oFolder.Files
$aAr[0][0] += 1
$aAr[$aAr[0][0]][0] = "File"
$aAr[$aAr[0][0]][1] = $oFile.Name
$aAr[$aAr[0][0]][2] = $oFile.ParentFolder.Path
Next
EndIf
EndFunc
Re: [..] Lister dossier puis fichier
Posté : lun. 18 mars 2013 11:24
par mikell
Merci
La version 2 va bien mais la version 1 me renvoie une erreur :
Line 56 :
$oRs.AddNew($aNames, $aValue)^ ERROR
Error: The requested action with this object has failed.
Re: [..] Lister dossier puis fichier
Posté : lun. 18 mars 2013 12:36
par GaRydelaMer
Ça marche nickel chez moi et au taf.
Les 2 pc sont sous Win7, parcours d'un dossier sur un disque D:
Tu as chois quel dossier de départ ?, je suis en train de tester j'ai des soucis si on met c:\ avec les dossier spéciaux style $Recycle.bin, Document & Settings
Je cherche à contourner le problème.
Re: [..] Lister dossier puis fichier
Posté : lun. 18 mars 2013 13:51
par mikell
XP SP3 32bits, dossier de départ : bureau (@desktopdir)
Donc effectivement ya du Document & Settings et plein de références à des dossiers spéciaux
Re: [..] Lister dossier puis fichier
Posté : mar. 19 mars 2013 13:55
par GaRydelaMer
Voila la version que j'utilise depuis un moment déjà.
Super rapide et assez flexible.
http://www.autoitscript.com/forum/topic ... -2-dec-12/
Prendre la version dans le zip, le forum US a une mauvaise tendance de supprimer les "\".
Re: [..] Lister dossier puis fichier
Posté : mar. 19 mars 2013 16:17
par Tlem
Si les choses n'ont pas changées depuis la dernière fois que j'ai testé cette fonction, je tiens à rappeler qu'en cas d'utilisation récursive fichiers + dossiers, la totalité des dossiers 'scannés' est retourné avec le résultat de la recherche (ceci correspondant à une fonctionnalité voulue par Melba et non un bug quelconque).
Edit : Après contrôle, je confirme le renvoi du nom de tous les dossiers scannés en mode récursif fichiers + dossiers, même si ceux-ci ne correspondent pas au masque de recherche.
Ceci signifie que pour une recherche de fichiers et dossiers portant un certain nom, vous devez utiliser la fonction deux fois :
- 1 fois en recherche de fichiers
- 1 fois en recherche de dossiers. ^^
Re: [..] Lister dossier puis fichier
Posté : mar. 19 mars 2013 16:21
par GaRydelaMer
C'est exact, mais y a un moyen simple c'est d'ajouter le dernier "\" dans le chemin de départ de la recherche ainsi dans le tableau les dossier comporteront aussi le dernier "\"
$arr[n] = "c:\xxx\" on reconnaitra le dossier avec le dernier caractère If StringRight($arr[n], 1) = "\" Then on a un dossier
$arr[n] = " c:\xxx\xx.aa" ici un fichier
Pour plus d'info voir la doc de la fonction dans l'UDF