Return the recent file among other by subdirectory

rated by 0 users
This post has 15 Replies | 3 Followers

Top 100 Contributor
Posts 34
f.lemanie Posted: 02-08-2013 8:12 AM

Hello,

Some users synchronize their data with synctoy (computer <-> server). I just want to scan folders to find their synctoy files (synctoyxxxxx.dat) and compare its LastWrite Time to compare to de date of the day.

I have 2 problems now:

-1) Synctoy generate several .Dat files. I want to get the more recent. I easily found the command for this but it runs with a single directory. When it exists several subfolders containing .dat files, the script returns just the last one .dat file ! I want to return the more recent .dat file for each folder containing a .dat file and write-host (or log) "more recent file - directory" for each.

-2) How return the number of days beetwen today and the more recents .dat file ?

 This is thmy script below (for 1 subfolder)

$PathFile =  "\\network\Secteur Est"

$File = gci $PathFile -Include synctoy*.dat -Recurse -Force -ErrorAction SilentlyContinue |

            Sort-Object {$_.lastwritetime} -Descending | Select-Object -First 1

I tried a lot of test with Foreach and If but more I try and more it seems to be difficult for me....

Thanks a lot for your answers..

Top 10 Contributor
Posts 1,213
Top Contributor

Hey,

 

For question one, I think this would be solved by grouping the files by Directory. Then you can select the first one for each folder. This is what I am doing with the Group-Object Cmdlet.

For question two, use calculated properties, that is the '@{Name='DayDifference';Expression={((Get-Date).Date - $_.LastWriteTime.Date).TotalDays}}' portion of this one-liner

 

So try this code and see how it works out for you:

Get-ChildItem -Path $PathFile -Include synctoy*.dat -Recurse -Force -ErrorAction SilentlyContinue | 

Sort-Object -Property LastWriteTime -Descending |

Group-Object -Property Directory | ForEach-Object {

    $_.Group | Select-Object -First 1 | Select FullName,LastWriteTime,@{Name='DayDifference';Expression={((Get-Date).Date - $_.LastWriteTime.Date).TotalDays}}

}

Top 100 Contributor
Posts 34

GREAT !

Thanks !

Top 100 Contributor
Posts 34

What will be the method to link directories where there is a .dat file to e-mail addresses ?

Top 10 Contributor
Posts 1,213
Top Contributor

I am not sure what you mean there? Do you want to email the list of directories that contain .dat files?

Top 100 Contributor
Posts 34

Hello Jaap ! I hope your week-end was good !

Each subfolder where I will find .dat files are named like this : V01, V02, V03, V04, etc... Each subfolder belong to a user. For exemple V01 belong to misterX@mydomain.com, V02 belong to misterY@mydomain.com,  etc...

I would like send the result of the directory V01 to misterX@mydomain.com, V02 results to misterY@mydomain.com, etc...

Must I do a text file with e-amil adresses ?

 

Top 10 Contributor
Posts 1,213
Top Contributor

I would create a csv file that contains the folder names and email addresses and have the script match on that. Something along the lines of:

$NamesFolders = Import-Csv H:\NamesFolder.csv
Get-ChildItem -Path $PathFile -Include synctoy*.dat -Recurse -Force -ErrorAction SilentlyContinue | 
Sort-Object -Property LastWriteTime -Descending |
Group-Object -Property Directory | ForEach-Object {
    $_.Group | Select-Object -First 1 | Select FullName,Directory,LastWriteTime,@{Name='DayDifference';Expression={((Get-Date).Date - $_.LastWriteTime.Date).TotalDays}}
} | ForEach-Object {
    $Basename = Split-Path -Path $_.Directory -Leaf
    foreach ($Email in ($NamesFolders | Where-Object {$_.Folder -eq $Basename})) {
        # Create initial objects
        $smtpServer = "smtp.whatever.com"
        $msg = new-object Net.Mail.MailMessage
        $smtp = new-object Net.Mail.SmtpClient($smtpServer)
        #Email structure 
        $msg.From = "you@whatever.com"
        $msg.ReplyTo = "yourreplyto@whatever.com"
        $msg.To.Add($Email.EmailAddress)
        $msg.subject = "Files found $(get-date) in Folder: $($_.Directory)"
        $msg.body = Get-ChildItem $_.Directory -Force
        #Send email 
        $smtp.Send($msg)       
    }
}
This is based on a csv that looks something like this:
NamesFolders.csv:::
Folder,EmailAddress
V01,1@whatever.com
V02,2@whatever.com
V03,3@whatever.com
V04,4@whatever.com

Top 100 Contributor
Posts 34

Hello,

The script returns this error message :

Split-Path : Impossible de lier l'argument au paramètre « Path », car il a la valeur Null.

 

Au niveau de C:\Scripts_PS\temporaire\Synctoy.ps1 : 16 Caractère : 33

+                 $Basename = Split-Path -Path <<<<  $_.Directory -Leaf

    + CategoryInfo          : InvalidData: (:) [Split-Path], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SplitPathCommand

 

Top 10 Contributor
Posts 1,213
Top Contributor

Alright, so what do you see if you add $_ at line 16, make the line look like this:

 

$_;$Basename = Split-Path -Path $_.Directory -Leaf

Top 100 Contributor
Posts 34

Hi Jaap !

It returns

15/01/2013 10:34:39                                                                            27 \Secteur Est\V17                              

Split-Path : Impossible de lier l'argument au paramètre « Path », car il a la valeur Null.

 

Au niveau de C:\Scripts_PS\temporaire\Synctoy.ps1 : 14 Caractère : 36

+                 $_;$Basename = Split-Path -Path <<<<  $_.Directory -Leaf

    + CategoryInfo          : InvalidData: (:) [Split-Path], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SplitPathCommand

 

The same for each folder...

Top 10 Contributor
Posts 1,213
Top Contributor

Hmmm, I am not sure how regional settings affect the property names of Get-ChildItem. Could you show me the output when you run the following command:

ls | gm -membertype Property

Top 100 Contributor
Posts 34

see below :

PS C:\Windows\system32> ls | gm -membertype Property

 

 

   TypeName : System.IO.DirectoryInfo

 

Name              MemberType Definition

----              ---------- ----------

Attributes        Property   System.IO.FileAttributes Attributes {get;set;}

CreationTime      Property   datetime CreationTime {get;set;}

CreationTimeUtc   Property   datetime CreationTimeUtc {get;set;}

Exists            Property   bool Exists {get;}

Extension         Property   string Extension {get;}

FullName          Property   string FullName {get;}

LastAccessTime    Property   datetime LastAccessTime {get;set;}

LastAccessTimeUtc Property   datetime LastAccessTimeUtc {get;set;}

LastWriteTime     Property   datetime LastWriteTime {get;set;}

LastWriteTimeUtc  Property   datetime LastWriteTimeUtc {get;set;}

Name              Property   string Name {get;}

Parent            Property   System.IO.DirectoryInfo Parent {get;}

Root              Property   System.IO.DirectoryInfo Root {get;}

 

 

   TypeName : System.IO.FileInfo

 

Name              MemberType Definition

----              ---------- ----------

Attributes        Property   System.IO.FileAttributes Attributes {get;set;}

CreationTime      Property   datetime CreationTime {get;set;}

CreationTimeUtc   Property   datetime CreationTimeUtc {get;set;}

Directory         Property   System.IO.DirectoryInfo Directory {get;}

DirectoryName     Property   string DirectoryName {get;}

Exists            Property   bool Exists {get;}

Extension         Property   string Extension {get;}

FullName          Property   string FullName {get;}

IsReadOnly        Property   bool IsReadOnly {get;set;}

LastAccessTime    Property   datetime LastAccessTime {get;set;}

LastAccessTimeUtc Property   datetime LastAccessTimeUtc {get;set;}

LastWriteTime     Property   datetime LastWriteTime {get;set;}

LastWriteTimeUtc  Property   datetime LastWriteTimeUtc {get;set;}

Length            Property   long Length {get;}

Name              Property   string Name {get;}

 

Top 100 Contributor
Posts 34

I putted an expression :

Select LastWriteTime,@{Name='Jours de retard';Expression={((Get-Date).Date - _.LastWriteTime.Date).TotalDays}},@{Name='Secteur';Expression={$_.DirectoryName -replace '.+itinérants',''}}

 

that I finally replaced by :

 

Select Directory,LastWriteTime,@{Name='Jours de retard';Expression={((Get-Date).Date - $_.LastWriteTime.Date).TotalDays}}

 

Now it's running. The only problem is that in the body e-mail it returns the results in that form below :

with  $msg.body = $_

 

@{Directory=\\myServer\Secteur Est\V02; LastWriteTime=01/15/2013 17:42:01; Jours de retard=27}

 

or

 

with  $msg.body = $_ | fl

 

Microsoft.PowerShell.Commands.Internal.Format.FormatStartData Microsoft.PowerShell.Commands.Internal.Format.GroupStartData Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData Microsoft.PowerShell.Commands.Internal.Format.GroupEndData Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

 

Top 10 Contributor
Posts 1,213
Top Contributor

Depending on what kind of output you want you could use any of these examples:

msg.body = $_ | Format-List | Out-String

msg.body = $_ | Format-Table -Autosize | Out-String

msg.body = $_ | Out-String

Top 100 Contributor
Posts 34

Thanks Jaap.

Below is the final script :

 

 

$PathFile =  \\server\itinérants 

$NamesFolders = Import-Csv C:\tmp\NamesFolder.csv

 Get-ChildItem -Path $PathFile -Include synctoy*.dat -Recurse -Force -ErrorAction SilentlyContinue |

Sort-Object -Property LastWriteTime -Descending |

Group-Object -Property Directory |

ForEach-Object   {$_.Group | Select-Object -First 1 |

                                                           Select Directory,LastWriteTime,@{Name='Jours de retard';Expression={((Get-Date).Date - $_.LastWriteTime.Date).TotalDays}}

                                                           } |

                                                           ForEach-Object {

                                                           $Basename = Split-Path -Path $_.Directory -Leaf

                                                           foreach ($Email in ($NamesFolders | Where-Object {$_.Folder -eq $Basename}))

                                                                          {If (((Get-Date).Date - $_.LastWriteTime.Date).TotalDays -gt 7)

                                                                                         {                                                         

                                                     #Create initial objects

                                                                   $smtpServer = "mysmtpserver"

                                                                   $msg = new-object Net.Mail.MailMessage

                                                                   $smtp = new-object Net.Mail.SmtpClient($smtpServer)

                                                                   #Email structure

                                                                   $msg.From = "xxx@mydomain.com"

                                                                   $msg.ReplyTo = "xxx@mydomain.com"

                                                                   $msg.To.Add($Email.EmailAddress)

                                                                                         $msg.To.Add($Email.EmailAddress2)

                                                                                         $msg.To.Add($Email.EmailAddress3)

                                                                   $msg.subject = "!!! Retard SYNCTOY !!! : $($_.Directory)"

                                                                   $msg.body = $_ | Select @{Name='Répertoire Synctoy';Expression={$_.Directory -replace '.+Itinérants', ''}},`

                                                                                         @{Name='Dernière synchro';Expression={$_.LastWriteTime}},`

                                                                                         @{Name='Jours de retard';Expression={((Get-Date).Date - $_.LastWriteTime.Date).TotalDays}} | fl | Out-String

                                                                                         #Send email

                                                                   $smtp.Send($msg)

                                                                                         }

                                                                          }

                                                                                                                      }

 

Page 1 of 2 (16 items) 1 2 Next > | RSS
Copyright 2012 PowerShell.com. All rights reserved.