Detecting csv files in newly sub-folder in PowerShell - powershell

I have a folder called C:\2014-15 and new sub folders are created every month which contain csv files i.e
C:\2014-15\Month 1\LTC
C:\2014-15\Month 2\LTC
C:\2014-15\Month 3\LTC
How to write a script which would detect when a LTC sub folder is created for every month and move the csv files to N:\Test?
UPDATED:
$folder = 'C:\2014-15'
$filter = '*.*'
$destination = 'N:Test\'
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host
Copy-Item -Path $path -Destination $destination
}
The error I get is:
Register-ObjectEvent : Cannot subscribe to event. A subscriber with source identifier 'FileCreated' already exists.
At line:8 char:34
+ $onCreated = Register-ObjectEvent <<<< $fsw Created -SourceIdentifier FileCreated -Action {
+ CategoryInfo : InvalidArgument: (System.IO.FileSystemWatcher:FileSystemWatcher) [Register-ObjectEvent], ArgumentException
+ FullyQualifiedErrorId : SUBSCRIBER_EXISTS,Microsoft.PowerShell.Commands.RegisterObjectEventCommand

Credit to this post.
Notify on a different event: [IO.NotifyFilters]'DirectoryName'. This removes the need for $filter since filename events are not relevant.
You should also notify for renamed folders and created folders, making your final script something like this
$folder = 'C:\2014-15'
$destination = 'N:\Test'
$fsw = New-Object System.IO.FileSystemWatcher $folder -Property #{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'DirectoryName'
}
$created = Register-ObjectEvent $fsw -EventName Created -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "LTC") {
# do stuff:
Copy-Item -Path $folder -Destination $destination
}
}
$renamed = Register-ObjectEvent $fsw -EventName Renamed -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "LTC") {
# do stuff:
Copy-Item -Path $folder -Destination $destination
}
}
From the same console you can unregister since that console knows about $created and $renamed:
Unregister-Event $created.Id
Unregister-Event $renamed.Id
Otherwise you need to use this which is bit uglier:
Unregister-Event -SourceIdentifier Created -Force
Unregister-Event -SourceIdentifier Renamed -Force
Also, thanks for the question. I didn't realise these event captures existed in powershell until now...

Related

moving files in order dependant on file name with powershell

I use PS script with filesystemwatcher to monitor a folder. In this folder files need to be picked up in a specific order, not in the order they are created. So:
Files "blabla-Important1.xml", "blabla-Important2.xml" and "blabla-Important3.xml" are placed in the "pick-up folder". Filesystemwatcher wants to move the files according to the script. Now I need the files to be placed in the "destination folder" in the order I want, let's say:
"blabla-Important2.xml",
"blabla-Important4.xml",
"blabla-Important3.xml",
"blabla-Important1.xml".
Any suggestions? Thanks in advance!
Here's the (partial) script:
$folder = '.\tstA'
$filter = '*.xml'
$destination = '.\tstB'
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "$timeStamp The file '$name' was $changeType and moved for SFTP to $destination"
"$timeStamp The file '$name' was $changeType and moved for SFTP to $destination" | Set-Content
'.\tst.log'
Move-Item $path -Destination $destination -Force -Verbose
}

Copy-Item does not work with FileSystemWatcher

I'm trying to create a watch folder on a network share that simply copies files (300mb-20gb) in size to a destination folder. The FileSystemWatcher and subscription works great with small files (i.e. 1-3kb). However, larger files do not copy. I do see a copy is triggered in the verbose stream, but no file is copied to the destination folder.
$Folder = "\\10.11.233.91\vol_tx01\delivered_media"
$Filter = "*.mxf"
$destination = "C:\Users\Leeds TX 11\Desktop\support\Testy"
$Watcher = New-Object IO.FileSystemWatcher $Folder, $Filter -Property #{
NotifyFilter = [IO.NotifyFilters]'Filename, LastAccess'
}
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier `
FileCreated -Action {
$path = $event.SourceEventArgs.FullPath
$name = $event.SourceEventArgs.Name
$ChangeType = $event.SourceEventargs.ChangeType
$Timestamp = $event.TimeGenerated
Write-Host "The file '$name' was $ChangeType at $Timestamp"
Copy-Item $path -Destination $destination -Force -Recurse -Verbose
}
Combination of issue were at hand. Firstly thank you JohnLBevan for pointing out LastWrite should be the notifyfilter to use. Also found that in this case copy-item does not wait for the file transfer in the source directory to close. I fixed this by putting in a while loop waiting for the file to be locked:
##################### DANGER BOX ####################################
$Folder = "C:\Users\Leeds TX 12\Desktop\Source" #Source dir
$Filter = "*.mxf" # MXF Filter
$destination = "C:\Users\Leeds TX 12\Desktop\Destination" # Destination dir
################### Watch for file system events###########################
$Watcher = New-Object IO.FilesystemWatcher $Folder, $Filter -Property #{
NotifyFilter = [IO.NotifyFilters]'LastWrite, Filename'
}
################### Register filesystemwatcher & subscribe to notifyfilters #################
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier filecreated -Action {
$path = $event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$ChangeType = $Event.SourceEventargs.ChangeType
$Timestamp = $event.TimeGenerated
write-host "The file '$name' was $ChangeType at $Timestamp" # Debug
################# Wait for file lock collapse #########################################
while($True)
{
Try {
[IO.File]::OpenWrite($path).Close()
Break
}
Catch { Start-Sleep -Seconds 1}
}
#################### Copy item #############################
Copy-item $path -Destination $Destination -force -Recurse -Verbose}

Copy-Item does not copy item when actioned by filesystemwatcher

I'm trying to create a watch folder on a network share that simply copies files (300mb-20gb) in size to a destination folder. The filesystemwatcher and subscription works great with small files (i.e. 1-3kb). However, larger files do not copy. I do see a copy is triggered in the verbose stream, but no file is copied to the destination folder.
$Folder = "\\10.11.233.91\vol_tx01\delivered_media"
$Filter = "*.mxf"
$destination = "C:\Users\Leeds TX 11\Desktop\support\Testy"
$Watcher = New-Object IO.FileSystemWatcher $Folder, $Filter -Property #{
NotifyFilter = [IO.NotifyFilters]'Filename, LastAccess'
}
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier FileCreated -Action {
$path = $event.SourceEventArgs.FullPath
$name = $event.SourceEventArgs.Name
$ChangeType = $event.SourceEventargs.ChangeType
$Timestamp = $event.TimeGenerated
Write-Host "The file '$name' was $ChangeType at $Timestamp"
Copy-Item $path -Destination $destination -Force -Recurse -Verbose
}

Detecting Multiple subfolders within the main folder using Powershell

UPDATED:
Hi. Apologies if my question sounds vague. When I run both Scripts below together all the csv files from ES and LTC sub-folder end up in one folder instead of two folders. I have two separate scripts
to monitor two sub-folders LTC and ES and copy the files to the folders.
LTC Script:
$folder = 'C:\2014-15'
$destination = 'N:\Test'
$fsw = New-Object System.IO.FileSystemWatcher $folder -Property #{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'DirectoryName'
}
$created = Register-ObjectEvent $fsw -EventName Created -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "LTC") {
Copy-Item -Path $folder -Destination $destination
}
}
$renamed = Register-ObjectEvent $fsw -EventName Renamed -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "LTC") {
Copy-Item -Path $folder -Destination $destination
}
}
ES Script:
$folder = 'C:\2014-15'
$destination = 'N:\Test1'
$fsw = New-Object System.IO.FileSystemWatcher $folder -Property #{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'DirectoryName'
}
$created = Register-ObjectEvent $fsw -EventName Created -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "ES") {
Copy-Item "$item\*.csv" -Destination $destination
}
}
$created = Register-ObjectEvent $fsw -EventName Created -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "ES") {
Copy-Item "$item\*.csv" -Destination $destination
}
}
$folder = 'C:\2014-15'
$destination = 'N:\Test'
$destination1 = 'N:\Test1'
$fsw = New-Object System.IO.FileSystemWatcher $folder -Property #{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'DirectoryName'
}
$created = Register-ObjectEvent $fsw -EventName Created -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "LTC") {
Copy-Item -Path $folder -Destination $destination
}
}
$renamed = Register-ObjectEvent $fsw -EventName Renamed -Action {
$item = Get-Item $eventArgs.FullPath
If ($item.Name -ilike "LTC") {
Copy-Item -Path $folder -Destination $destination
}
}
$fsw = New-Object System.IO.FileSystemWatcher $folder -Property #{
IncludeSubdirectories = $true
NotifyFilter = [IO.NotifyFilters]'DirectoryName'
}
$created = Register-ObjectEvent $fsw -EventName Created -Action {
$item1 = Get-Item $eventArgs.FullPath
If ($item1.Name -ilike "ES") {
Copy-Item "$item1\*.csv" -Destination $destination1
}
}
$created = Register-ObjectEvent $fsw -EventName Created -Action {
$item1 = Get-Item $eventArgs.FullPath
If ($item1.Name -ilike "ES") {
Copy-Item "$item1\*.csv" -Destination $destination1
}
}

powershell, how to mointor a directory and move files over to another folder

I am using powershell 3. need to monitor a folder, if there are any image files, move them over to antoher folder.
here's my code, i test it, its not working, couldn't figure out what need to be fixed.
#<BEGIN_SCRIPT>#
#<Set Path to be monitored>#
$searchPath = "F:\download\temp"
$torrentFolderPath = "Z:\"
#<Set Watch routine>#
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $searchPath
$watcher.IncludeSubdirectories = $false
$watcher.EnableRaisingEvents = $true
$created = Register-ObjectEvent $watcher "Created" -Action {
Copy-Item -Path $searchPath -Filter *.jpg -Destination $torrentFolderPath –Recurse
}
#<END_SCRIPT>#
UPDATE:
I got it partially working. still have one issue left. lets start with an empty folder. I download an image (1.jpg) to the folder, nothing moved to Z: drive. then I download another image (2.jpg) to the folder. 1.jpg will be moved to Z: drive. seems like the newly created one never get moved over.
$folder = "F:\\download\\temp"
$dest = "Z:\\"
$filter = "*.jpg"
$fsw = new-object System.IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubDirectories=$false
NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
Move-Item -Path F:\download\temp\*.jpg Z:\
}
You have not registered the NotifyFilter. That is why your code is not working.
here is a sample which registers the NotifyFilter and prints the file details which was created
$folder = "c:\\temp"
$filter = "*.txt"
$fsw = new-object System.IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubDirectories=$false
NotifyFilter = [System.IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceVentArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host $path
Write-Host $name
Write-Host $changeType
Write-Host $timeStamp
}
Event action scripts run in a separate scope that only has access to global variables, so depending on your implementation you have have issues trying to use those variables in the action script. One way around without resorting to declaring global variables (bad mojo!) is to use an expandable string to create a script block with the variables expanded before you register the event:
$ActionScript =
[Scriptblock]::Create("Copy-Item -Path $searchPath -Filter *.jpg -Destination $torrentFolderPath –Recurse")
$created = Register-ObjectEvent $watcher "Created" -Action $ActionScript