0

I have this code:

$filestowatch=get-content C:\GT\files-to-watch.txt $adminFiles=dir C:\GT\admin\src\admin\wwwroot\content\less\ |? {$filestowatch -contains $_.Name} $userfiles=dir C:\GT\user-staging\src\user_staging\wwwroot\content\less\|? {$filestowatch -contains $_.Name} 

and in files-to-watch.txt

_dark.less _light.less 

This creates a list of adminFiles and a list of userFiles that my code uses.

However I have a problem in that some files are in directories under wwwroot. So I need to watch the files here:

\content\less\_dark.less \content\less\_light.less \lib\abc.txt \index.txt 

Can someone help and suggest how I could change this so code so that it works with directories and then filenames in the files-to-watch.txt.

Update - Here's the full code that I have come up with I tried vesper's suggestion but it seems not to work with my code.

$filestowatch=get-content C:\GT\files-to-watch.txt $adminFiles=dir C:\GT\admin\src\admin\wwwroot -recurse | ? { $fn=$_.FullName; ($filestowatch | % {$fn.contains($_)}) -contains $True} $userFiles=dir C:\GT\user-staging\src\user-staging\wwwroot -recurse | ? { $fn=$_.FullName; ($filestowatch | % {$fn.contains($_)}) -contains $True} foreach($userfile in $userFiles) { Write-Host "Checking" $userfile.FullName $exactadminfile= $adminfiles | ? {$_.Name -eq $userfile.Name} |Select -First 1 $filetext1=[System.IO.File]::ReadAllText($exactadminfile.FullName) $filetext2=[System.IO.File]::ReadAllText($userfile.FullName) $equal = $filetext1 -ceq $filetext2 # case sensitive comparison if ($equal) { break; } if($exactadminfile.LastWriteTime -gt $userfile.LastWriteTime) { Write-Host "Copying $exactadminfile.FullName to $userfile.FullName " Copy-Item -Path $exactadminfile.FullName -Destination $userfile.FullName -Force } else { Write-Host "Copying $userfile.FullName to $exactadminfile.FullName " Copy-Item -Path $userfile.FullName -Destination $exactadminfile.FullName -Force } } 

and my files to watch

content\less\_dark.less content\less\_light.less 

I think this is close but it gives me this error:

PS C:\Windows\system32> C:\GT\watcher.ps1 dir : Cannot find path 'C:\GT\user-staging\src\user-staging\' because it does not exist. At C:\GT\watcher.ps1:8 char:12 + $userFiles=dir C:\GT\user-staging\src\user-staging\wwwroot -recurse | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ObjectNotFound: (C:\GT\user-staging\src\user-staging\:String) [Get-ChildItem], ItemNotFoundException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand 

2 Answers 2

2

You need to filter $_.FullName against the array that contains partial paths. Say, your $filestowatch contains the values you've listed. Then you use this trick to quickly produce an "any match" filter out of $_.FullName:

$adminFiles=dir C:\GT\admin\src\admin\wwwroot -recurse | ? { $fn=$_.FullName; ($filestowatch | % {$fn.contains($_)}) -contains $True} 

This runs a substring check against $filestowatch that generates an array of booleans, and if any of them is $True, there is a match, and the Where-Object filter passes the found FileInfo object through the pipeline.

Sign up to request clarification or add additional context in comments.

3 Comments

thanks. All this seems pretty complicated compared to the usual code you write. I am learning a lot from your answers.
I tried your suggestion. I think it's almost working but I am getting another error and not sure if it is related to your suggestion. Do you have any ideas?
You mistyped the second user-staging, according to your original code, there's an underscore. Be careful next time.
2

I broke out the file and folder paths into variable which made it easier for testing and readability. Feel free to change as you see fit of course. Much like Vesper did you need to use -recurse if you are concerned about files in parent directories. What I did hear that was different was create a regex string that is built from the paths in the text files. Also I apply the filter once by combining the output of the two called to Get-ChildItem

$adminfilePath = "C:\GT\admin\src\admin\wwwroot" $userfilePath = "C:\GT\user-staging\src\user_staging\wwwroot" $filesToWatchPath = "C:\GT\files-to-watch.txt" $filter = (Get-Content $filesToWatchPath | ForEach-Object{[regex]::Escape($_)}) -join "|" $adminFiles = @(Get-ChildItem $adminfilePath -Recurse | Select-Object -ExpandProperty FullName) $userfiles = @(Get-ChildItem $userfilePath -Recurse | Select-Object -ExpandProperty FullName) $adminFiles + $userfiles | Where-Object{$_ -match $filter} 

With your example text we create a filter that looks like

_dark\.less|_light\.less 

Using [regex]::Escape() we escape any regex control characters that might appear in your string like the period. The we use -join to create a matching group.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.