Search multiple folders in multiple servers list - powershell

I'm trying to create a ps1 that can search multiple folders in multiple servers list, but seems didn't work. Something wrong with the *folder I guess. Sorry I'm very new to this.
$folders = get-content "C:\temp\folders.txt"
get-content c:\temp\servers.txt | Foreach {
Get-ChildItem -Path "c:\temp" -include *folders -Recurse -ErrorAction
silentlycontinue} | export-csv c:\Temp\results.csv

You're reading a textfile with (presumably) a list of server names to probe, but in your code you do nothing with that other than iterate this list..
Try
$folders = Get-Content 'C:\temp\folders.txt' # the list of foldernames to look for
Get-Content 'C:\temp\servers.txt' | ForEach-Object {
# construct a UNC path to the C:\Temp folder on the remote server (\\server\c$\temp)
# the $_ Automatic variable contains one servername in each iteration
$remotePath = "\\$_\C$\temp"
Get-ChildItem -Path $remotePath -Include $folders -Directory -Recurse -ErrorAction SilentlyContinue |
# select properties you need
Select-Object #{Name = 'ComputerName'; Expression = {$_}}, Name, FullName, CreationTime, LastAccessTime, LastWriteTime
} | Export-Csv 'C:\temp\results.csv' -NoTypeInformation
OR
Have the remote servers do the work and return the results to you. You may need to add -Credentials on Invoke-Command:
$folders = Get-Content 'C:\temp\folders.txt' # the list of foldernames to look for
Get-Content 'C:\temp\servers.txt' | ForEach-Object {
Invoke-Command -ComputerName $_ -ScriptBlock {
# this is running on the remote computer, so it uses it's own LOCAL path
# the $folders variable needs to be scoped '$using:folders', otherwise it is unknown in the scriptblock
Get-ChildItem -Path 'C:\temp' -Include $using:folders -Directory -Recurse -ErrorAction SilentlyContinue |
# select and output the properties you need
Select-Object #{Name = 'ComputerName'; Expression = {$env:COMPUTERNAME}}, Name, FullName, CreationTime, LastAccessTime, LastWriteTime
}
} | Export-Csv 'C:\temp\results.csv' -NoTypeInformation

Related

Powershell Get-ChildItem Exclude Default Windows Folders

I want to search for files with .2fa extension on remote computers. I can find the files I want, but it takes a long time to get to the second computer because it scans all windows files.
I tried the -exclude and where arguments but they do not work.
Could you please help me? Thanks.
$ServerList = Import-Csv 'C:\PC.CSV'
$result = foreach ($pc in $ServerList.barkod) {
$exclude = '*ProgramData*','*Program Files*','*Program Files (x86)*','*Windows*'.'*winupdate*'
$sourcepath = 'c$'
Get-ChildItem -Path \\$pc\$sourcepath -Recurse | Where-Object { $_.Name -like "*.2fa" } |
where {$_.name -notin $Exclude}
}
$result
I tried
-Exclude $exclude
-where {$_.name -notin $Exclude}
-exclude doesn't work with subdirectories or -filter:
Get-ChildItem -Path \\$pc\$sourcepath\ -exclude $exclude |
get-childitem -recurse -filter *.2fa
Since you are looking for files with a certain extension, use the -Filter parameter.
This will be the fastest option to search for only .2fa files, disregarding all others. (Filter works on the Name property)
If you want to search the C: drive, you are bound to hit Access Denied exceptions and because to exclude a list of foldernames using post-process with a Where-Object clause,
Get-ChildItem will try and search in these folders you need to apend -ErrorAction SilentlyContinue to the command
$exclude = 'ProgramData','Program Files','Program Files (x86)','Windows'.'winupdate'
# create a regex string you can use with the `-notmatch` operator
# each item will be Regex Escaped and joined together with the OR symbol '|'
$excludeThese = ($exclude | ForEach-Object { [Regex]::Escape($_) }) -join '|'
$ServerList = (Import-Csv 'C:\PC.CSV').barkod
$sourcepath = 'c$'
$result = foreach ($pc in $ServerList) {
Get-ChildItem -Path "\\$pc\$sourcepath" -Filter '*.2fa' -File -Recurse -ErrorAction SilentlyContinue |
Where-Object {$_.DirectoryName -notmatch $excludeThese}
}
$result

Copy folders from server to another - Powershell

I am trying to come up with a script to copy folders from one server to another. I might be going about this wrong, but I'm try to copy the directories from one server into an array, copy the directories from the second server into an array, compare them and then create the folders needed in the server that doesn't have them:
[array]$folders = Get-ChildItem -Path \\spesety01\TGT\TST\XRM\Test -Recurse -Directory -Force -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
[array]$folders2 = Get-ChildItem -Path \\sutwove02\TGT\TST\XRN -Recurse -Directory -Force -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
$folders | ForEach-Object {
if ($folders2 -notcontains "$_") {
New-Item "$_" -type directory
}
}
The issue is that the "$_" (in the ForEach loop)refers to the server in "$folders" and when I run the script, I get an error that the folder already exists. Is there some way to specify to copy the folders to the new server? I accept that my approach might be completely off on this and I might be making it harder than it needs to be.
<#
.SYNOPSIS
using path A as reference, make any sub directories that are missing in path B
#>
Param(
[string]$PathA,
[string]$PathB
)
$PathADirs = (Get-ChildItem -Path $PathA -Recurse -Directory).FullName
$PathBDirs = (Get-ChildItem -Path $PathB -Recurse -Directory).FullName
$PreList = Compare-Object -ReferenceObject $PathADirs -DifferenceObject $PathBDirs.replace($PathB,$PathA) |
Where-Object -Property SideIndicator -EQ "<=" |
Select-Object -ExpandProperty 'InputObject'
$TargetList = $PreList.Replace($PathA,$PathB)
New-Item -Path $TargetList -ItemType 'Directory'

With PowerShell's Get-ChildItem, how to I list matching files AND count them at the same time

How do I show AND count matching files using a single Get-ChildItem command in PowerShell? Currently I am using two Get-ChildItem commands, the first to count, the second to display the files - works fine but it is not very effective when scanning an entire disk ...
Command to count the matches:
$count = Get-ChildItem -Path $searchLocation -Filter $filename -Recurse -ErrorAction SilentlyContinue | Measure-Object | %{$_.Count}
Command to display the files:
Get-ChildItem -Path $searchLocation -Filter $filename -Recurse -ErrorAction SilentlyContinue | %{$_.FullName}
As Get-ChildItem is returning an array, its size is stored in .Length member and explicit measurement is not needed. Thus, store the file names in the same collection and then print length for number of entries and iterate the collection for file names. Swapping the variable name as $files to reflect this like so,
$files = Get-ChildItem -Path $searchLocation -Filter $filename `
-Recurse -ErrorAction SilentlyContinue
# ` can used to divide command into multiple lines (and work-around for markup stupidness)
# prints the number of items
$files.Length
# prints the full names
$files | %{$_.FullName}
An alternative method is to add a file number to each file as it processes.
$i = 1
$Files = Get-ChildItem -Path $searchLocation -Filter $filename -Recurse -ErrorAction SilentlyContinue
Foreach($Item in $Files) {
$Item | Add-Member -MemberType NoteProperty -Name FileNo -Value $i
$i++
}
$Files | Select-Object FileNo, Fullname
You can then see the order the files were processed, get the last file number by doing $File[-1].FileNo. And it will maintain all the additional file metadata suck as CreationTime, DirectoryName, VersionInfo etc.
Simply like this :
$AllFile=Get-ChildItem $searchLocation -File -Filter $filename -Recurse | select FullName
$AllFile.Count
$AllFile.FullName
Or you can ad a rank into your loop like this :
$Rang=0
Get-ChildItem "c:\temp" -File -Filter "*.txt" -Recurse | %{
$Rang++
Add-Member -InputObject $_ -Name "Rang" -MemberType NoteProperty -Value $rang
$_
} | select Rang, FullName

Query File Version using powershell

I have a code that let me query one file version at the time.How can I query all file version inside of this registry key or if I just want to query specific files including firefox, chrome, etc.?
(Get-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\App Paths\communicator.exe').'(Default)' | ForEach-Object {
Get-ChildItem -Path $_ | Select-Object -ExpandProperty VersionInfo | Select FileDescription,ProductVersion
} | Format-Table -AutoSize
Instead of providing a literal path you should run Get-ChildItem on the "folder" the registry keys are contained in you are interested in. The result of this you pipe to your piece of code ... like this:
$Path = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\App Paths'
Get-ChildItem -Path $Path |
ForEach-Object {
Get-ItemProperty -Path $_.PSPath |
Select-Object -ExpandProperty '(default)' -ErrorAction SilentlyContinue |
ForEach-Object {
Get-Item -Path $_ -ErrorAction SilentlyContinue |
Select-Object FullName -ExpandProperty VersionInfo
}
} |
Format-Table -AutoSize

List file count by subfolder

I am trying to use powershell to produce a list of folder names and how many files are in each folder.
I have this script
$dir = "C:\Users\folder"
Get-ChildItem $dir -Recurse -Directory | ForEach-Object{
[pscustomobject]#{
Folder = $_.FullName
Count = #(Get-ChildItem -Path $_.Fullname -File).Count
}
} | Select-Object Folder,Count
Which lists the file count, but it puts the full path (i.e. C:\Users\name\Desktop\1\2\-movi...). Is there any way to just display the last folder ("movies") as well as save the result to a .txt file?
Thank you
Instead of $_.FullName, use $_.Name to only get the directory name.
Your Select-Object call is redundant - it is effectively a no-op.
While it's easy to send the results to a .txt file with >, for instance, it's better to use a more structured format for later programmatic processing.
In the simplest form, that means outputting to a CSV file via Export-Csv; generally, however, the most faithful way of serializing objects to a file is to use Export-CliXml.
Using Export-Csv for serialization:
$dir = 'C:\Users\folder'
Get-ChildItem -LiteralPath $dir -Recurse -Directory | ForEach-Object {
[pscustomobject] #{
Folder = $_.Name
Count = #(Get-ChildItem -LiteralPath $_.Fullname -File).Count
}
} | Export-Csv -NoTypeInformation results.csv
Note that you could streamline your command by replacing the ForEach-Object call with a Select-Object call that uses a calculated property:
$dir = 'C:\Users\folder'
Get-ChildItem -LiteralPath $dir -Recurse -Directory |
Select-Object Name,
#{ n='Count'; e={#(Get-ChildItem -LiteralPath $_.Fullname -File).Count} } |
Export-Csv -NoTypeInformation results.csv
You mean something like this...
Clear-Host
Get-ChildItem -Path 'd:\temp' -Recurse -Directory |
Select-Object Name,FullName,
#{Name='FileCount';Expression = {(Get-ChildItem -Path $_.FullName -File -Recurse| Measure-Object).Count}} `
| Format-Table -AutoSize
# Results
Name FullName FileCount
---- -------- ---------
abcpath0 D:\temp\abcpath0 5
abcpath1 D:\temp\abcpath1 5
abcpath2 D:\temp\abcpath2 5
Duplicates D:\temp\Duplicates 12677
EmptyFolder D:\temp\EmptyFolder 0
NewFiles D:\temp\NewFiles 4
PngFiles D:\temp\PngFiles 4
results D:\temp\results 905
...