Question Comp. d'objets : différences de résultats (Résolu)

Plus d'informations
il y a 17 ans 11 mois #2096 par sonic
Bon je creuse mais je dois crueser à coté :laugh:

Je n'ai besoin de detecter que les fichiers qui sont supprimés et renomés . mon script focntionne deja pour le reste mais c'est parceque il n'a pas besoin de l'objet importé . J'ai donc fait un script reduit pour test qui ne s'occupe que des suppressions pour l'instant .
En boucle infinit ca focntionne:
[code:1]
# \"fichiers supprimés\" >> $fichier_log

# # Mise en variable des fichiers supprime deduits en fonction des comparaisons ci dessous .
# $d=$ancien | where-object {((get-childitem $rep -r $_) -eq $null)} |`
# format-table Lastwritetime,name,`
# @{label=\"partofdirectoryname\"; `
# expression={$_.DirectoryName.substring($_.DirectoryName.lastindexof(\":\"«»)+14)}} `
# -autosize -hideTableHeaders
[/code:1]
Mais je supprime la boucle infini . J'ai donc besoin de pouvoir exporter puis importer une image de l'etat pour l'itération suivante .
J'ai donc essayé d'exporté pui de reimpoter l'etat . mais les traitemtn ne focntionne plus :blink: J'ai donc essayé ce qui ma été dis ici :

$d=\"\"
$reptrv =\"c:\dev\"
$rep =\"C:\repsurveil\"

# get-childitem $rep -r |Where-Object {$_.PSIsContainer -eq 0} | export-clixml $reptrv\tutu.xml # me ser a cree mon ancien de temps en temps


$ancien = import-clixml $reptrv\tutu.xml

$new=get-childitem $rep -r |Where-Object {$_.PSIsContainer -eq 0} | export-clixml $reptrv\new.xml
$new=import-clixml $reptrv\new.xml

# \"fichiers supprimés\"

# $d=$ancien | where-object {(($news $_) -eq $null)}

$d=$ancien | where-object { !($news -contains $_)} | format-table Lastwritetime,name,directoryname

\"$d\"

a la sortie j'ai mes vairablse ok [code:1]
PS C:\dev> $ancien


Répertoire : Microsoft.PowerShell.Core\FileSystem::C:\repsurveil


Mode LastWriteTime Length Name
----

----
04/04/2008 15:40 0 abcdef.txt
04/04/2008 16:04 0 v (1).txt
04/04/2008 16:04 0 v (2).txt
04/04/2008 16:04 0 v.txt


PS C:\dev> $new


Répertoire : Microsoft.PowerShell.Core\FileSystem::C:\repsurveil


Mode LastWriteTime Length Name
----

----
04/04/2008 15:40 0 abcdef.txt
04/04/2008 16:04 0 v (2).txt
04/04/2008 16:04 0 v.txt

[/code:1]

On vois bien que v1.txt a été supprimé . Je pensais donc l'avoir dans $d . Et bien non . Je voulais les fichiers supprimés dans cette variable . Au lieu de ca j'ai (j'ai testé au cas ou les 2 solutions avec ou sans le ! qui inversse) .

[code:1]
PS C:\dev> $d=$ancien | where-object { !($news -contains $_)} | format-table Lastwritetime,name,directoryname
PS C:\dev> $d

LastWriteTime Name DirectoryName
----
04/04/2008 15:40:57 abcdef.txt C:\repsurveil
04/04/2008 16:04:40 v (1).txt C:\repsurveil
04/04/2008 16:04:47 v (2).txt C:\repsurveil
04/04/2008 16:04:55 v.txt C:\repsurveil


PS C:\dev> $d=$ancien | where-object { ($news -contains $_)} | format-table Lastwritetime,name,directoryname
PS C:\dev> $d
[/code:1]
Dans un cas elle est vide dans l'autre elle contien ancien !!! Bref ca fonctione pas . Je ne comprend pas ,pourquoi mon idée de départ ne fonctionne pas . A savoir que puisque j'importait un objet (dans mes variable anciennement faite a la volées) mes traitements devaient rester bon .
Je cherche encore ....<br><br>Message édité par: sonic31, à: 4/04/08 16:46

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 11 mois #2098 par Laurent Dardenne
Le mieux, enfin à prioris, est d'utiliser Compare-object.

Ensuite de déterminer les nouveaux fichiers et ceux supprimés cela semble relativement aisé, bien que...
Quant aux fichiers renommés cela s'avère un peu plus délicat, car la \&quot;clé primaire\&quot; se trouve être le nom du fichier, compare-objet, qui travaille sur des ensembles, ne peut pas nous 'dire' si c'est un nouveau fichier ou un fichier renommé, il y voit seulement une diffèrence.

Je regarde ça de plus près.

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 11 mois #2100 par Laurent Dardenne
Salut,
voici un début de solution. Comme le Cmdlet Compare-Object est un opérateur ensembliste on ne peut retrouver que des informations du type \&quot;existe\&quot; \&quot;n'existe pas\&quot;.
Les limites :
1)Une partie des modifications peuvent ne pas être vues, ex
date1 -&gt;Photo 1
Date1+5mn opération create dir, create file 1 , create file 2
Date2 opération delete file 2
Date3 Photo 2: les opérations sur file 2 n'apparaissent pas.
Normal puisque NFTS n'assure pas ce service de versionning/historique
2)Une opération de renommage est vue comme une suppression+une création, on a donc 2 informations au lieu d'une.
Comme il n'y a pas de notion d'identifiant persistent, difficile de limiter ce 'bruit'. Sauf si l'on est certain que la date de céation d'un fichier est unique pour chaque entrée NTFS.

Donc on récupére les données d'origine dans $ancien et les nouvelles dans $new
[code:1]
$Ancien=get-childitem -r
$New=get-childitem -r
[/code:1]
On compare les 2 collections
[code:1]
compare-object $new $ancien -prop name -includeequal
[/code:1]
que l'on ventile dans 3 tableaux à l'aide de la fonction Répartir
[code:1]
Function Répartir ($list)
{
$global:Egaux =@()
$global:«»Supprime =@()
$global:Nouveaux =@()
foreach ($Item in $List)
{
switch ($Item.SideIndicator)
{
'==' {$global:Egaux +=$item}
'&lt;=' {$global:Nouveaux +=$item}
'=&gt;' {$global:«»Supprime +=$item}
}
}
}
[/code:1]
Ensuite on visualise le résultat à l'aide de la fonction visu
[code:1]
function visu
{
Write-host \&quot;Ancien :\&quot; -f Yellow
$ancien|ft fullname,CreationTime,lastwritetime,lastaccesstime
Write-host \&quot;Nouveau :\&quot; -f Yellow
$new|ft fullname,CreationTime,lastwritetime,lastaccesstime
Write-host \&quot;Egaux :\&quot; -f Green
$Egaux
Write-host \&quot;Nouveaux :\&quot; -f Green
$Nouveaux
Write-host \&quot;Supprimé :\&quot; -f Green
$Supprime
}
[/code:1]
On a donc
[code:1]
$Ancien=get-childitem -r
$New=get-childitem -r
répartir(compare-object $new $ancien -prop name -includeequal)
Visu
[/code:1]
Sur qq tests simples autour d'un répertoire et de 5 fichiers le résultat est correcte.Je te laisse effectuer des tests + importants.

Ensuite pour éviter les 2 informations lors d'un renommage de fichier, j'ai essayé cette piste :
[code:1]
#rename sans autre modification.
ren t3.txt t5.txt
#Nouvelle photo
$New=get-childitem -r
# Pour une opération de renommage on a 2 informations : un fichier supprimé(t3.txt) et un nouveau fichier(t5.txt)
Répartir (compare-object $new $ancien -prop name -includeequal)
visu

# on interroge sur la date de création et pas sur le nom
#DANS CE CAS, le résultat est ok mais on ne connait plus le nom
#Si on passe l'objet dans le pipe, l'information \&quot;SideIndicator\&quot; n'est pas propagée/ajoutée. A revérifier...
Répartir (compare-object $new $ancien -prop creationtime -includeequal)
visu
# Si on interroge sur les 2 propriétés on revient au premier cas, à savoir une interrogation uniquement sur le nom
Répartir (compare-object $new $ancien -prop creationtime,name -includeequal)
visu

#On essaie de retrouver les informations(creationtime,name,SideIndicator) au sein d'un objet
$A=compare-object $ancien $ancien -prop creationtime,name -includeequal
$n=compare-object $new $new -prop creationtime,name -includeequal
#On récupére une seule information (le fichier renommé se retrouve dans le tableau Egaux) mais on ne connait plus le nom d'origine du fichier (pas d'historique)
Répartir(compare-object $n $a -prop creationtime -includeequal -passthru)
visu
[/code:1]
Je ne suis pas certain que PS soit adapté à ce besoin. De plus la volumétrie à traiter jouera bien évidemment un rôle important.

Une autre approche serais d'utiliser un SGBD ou d'interroger le référentiel de sauvegarde (s'il le permet) ou encore le gestionnaire de source Subversion mais au prix d'une duplication de données, là tu as le versionning et l'historique.

Ce sera peut être une des évolutions de NTFS...

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 11 mois #2104 par sonic
Merci beaucoup .
J'ai un peu regarder ce We entre la tondeuse et le motoculteur, j'ai donc eu un peu de mal a me concentrer .
Bref , je vais tester tout cela des aujourd hui .

Par contre , parceque je voudrais comprendre quand meme , pour de futur scripts et par curiosité .
Voici comment je faisait quand j'utilisais la boucle infinit , donc sans importer d'objet .
[code:1] # Mise en variable des fichiers renome deduits en fonction des comparaisons ci dessous .
# $c=$actuel | where-object {(($ancien | foreach {$_.name}) -notcontains $_.name)-and ($_.creationtime -lt $derniercheck)}`
# | format-table Lastwritetime,name,`
# @{label=\&quot;partofdirectoryname\&quot;; `
# expression={$_.DirectoryName.substring($_.DirectoryName.lastindexof(\&quot;:\&quot;«»)+14)}} `
# -autosize -hideTableHeaders
get-date &gt;&gt; $fichier_log


# \&quot;fichiers supprimés\&quot; &gt;&gt; $fichier_log

# # Mise en variable des fichiers supprime deduits en fonction des comparaisons ci dessous .
# $d=$ancien | where-object {((get-childitem $rep -r $_) -eq $null)} |`
# format-table Lastwritetime,name,`
# @{label=\&quot;partofdirectoryname\&quot;; `
# expression={$_.DirectoryName.substring($_.DirectoryName.lastindexof(\&quot;:\&quot;«»)+14)}} `
# -autosize -hideTableHeaders[/code:1]

Puisque qu'il me semblait qu'un objet importé était identique (mais mort) pourquoi cela ne fonctionne pas si $ancien est importé de l'itération précédente ?
A noter que comme cela la charge devient vite problèmatique . Sur un serveur correct c'est + de 5 minute de traitement pour environ 1000 fichiers .

Sinon dans un premier temps je testerai sans la détection de la double action \&quot;suppression renomage\&quot; vu que je faisais sans avant . Je le mettrais en place juste apres .
Ce n'est pas très grave si je détecte pas les modif fantomes entre 2 itérations (ajout , supression d'un meme fichier sans passer par une photo) . J'ai deja signaler qu'il faudrait plutot une GED , sans succés .
Bref entre ca et la charge sur les serveurs non ce n'est clairement pas adapté . Mais pour le faire comprendre ..... De tout façon ca ne me géne pas trop ca me permet de faire du powershell :lol: .

Je teste tout ca .

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 11 mois #2105 par sonic
Décidément avec ce script j'en vois des choses !!!<br><br>Message édité par: sonic31, à: 7/04/08 12:49

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 11 mois #2107 par Laurent Dardenne
Salut,
sonic31 écrit:

Merci beaucoup .

De rien :)
sonic31 écrit:

Puisque qu'il me semblait qu'un objet importé était identique (mais mort) pourquoi cela ne fonctionne pas si $ancien est importé de l'itération précédente ?

Je ne suis pas sûr que les termes \&quot;identique (mais mort)\&quot;soient les bons dans ce contexte.
Je dirais \&quot;Un objet valide à un instant T\&quot;(cf. photo). Sans rentrer dans les détails car sous .NET il existe une notion de résurrection...
Ce que tu recharges est bien un objet mais c'est plutôt la représentation d'un objet, le fichier du disque.

Je suppose que l'erreur que tu avais
[code:1]
where-object {((get-childitem $rep -r $_) -eq $null
[/code:1]
est du au fait que $_ est lié à l'option -Filter, et n'a rien avoir avec un pb de persistance.
sonic31 écrit:

A noter que comme cela la charge devient vite problèmatique. Sur un serveur correct c'est + de 5 minute de traitement pour environ 1000 fichiers .

Là je pense que tu as un pb d'écriture des instructions du pipe
[code:1]
..| where-object {(($ancien | foreach {$_.name}) -notcontains $_.name)-and
($_.creationtime -lt $derniercheck)}`
[/code:1]
L'imbrication de boucle dans le pipe doit y être pour beaucoup et je ne suis pas certain, là faut étudier le code dans le détails, que ce pipe soit fluide.

Je ne sais pas si le parseur réorganise ni comment il fait mais essaie de placer ce test en premier
[code:1]
$_.creationtime -lt $derniercheck
[/code:1]
et ici il me semble qu'il y ait une redondance
[code:1]
($ancien | foreach {$_.name}) -notcontains $_.name
[/code:1]
je verrais plutot ceci
[code:1]
($ancien -notcontains $_.name)
[/code:1]

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.048 secondes
Propulsé par Kunena