Assume I have 2 folders A and B
Folder A contains files like "food.txt", "drinks.txt", ...
Folder B contains files like "beverage.txt", "entre.txt",...
Is there a way using dir (gci) or any command to get an output like
"beverage.txt", "drinks.txt", "entre.txt", "food.txt",..
Just use:
Get-ChildItem -File -Recurse | Select-Object -ExpandProperty Name
-File will list only files
-Recurse will also get all folder under the given one
Select-Object -Expandproperty Name will give you only the filename
If the files are located somewhere completely different you can just give GCImultiple Paths:
Get-ChildItem -File -Path "PathToFolderA","PathToFolderB" | Select-Object -ExpandProperty Name
The pre PSv3 way to check for file/directory is to inspect the PSIsContainer property in a Where-Object
So this line will return:
PS A:\> Get-ChildItem -Path "Folder A","Folder B" |Where-object {!$_.PSIsContainer}| Select-Object -ExpandProperty Name
drinks.txt
food.txt
beverage.txt
entre.txt
Taking your question literal with double quotes and separated with ,
(Get-ChildItem -Path "Folder A","Folder B" |Where-object {!$_.PSIsContainer}|ForEach-Object { '"{0}"' -f $_.Name}) -join ', '
"drinks.txt", "food.txt", "beverage.txt", "entre.txt"
To have output sorted, just insert a |Sort-Object Name
(Get-ChildItem -Path "Folder A","Folder B" |sort Name|Where-object {!$_.PSIsContainer}|ForEach-Object { '"{0}"' -f $_.Name}) -join ', '
"beverage.txt", "drinks.txt", "entre.txt", "food.txt"
Related
I am trying to create a PowerShell script to fetch the root folder's name where in their subdirectories files with error names are present with today's date. Below is the sample code I have tried so far to pick the folder names.
Root Log folder - C:\Errorlogs, contains many other application log level folders.
$targetDir="C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*"|
where {([datetime]::now.Date -eq $_.lastwritetime.Date)} |
select FullName
I have tried the above code; however, it's giving me the whole path as result, whereas I only need the folder name.
Result - C:\Errorlogs\AsyncCreateUsersAPIProcessor\202302\04\Error.txt
Required - AsyncCreateUsersAPIProcessor
Use string LastIndexOf and SubString
$rootPath = "C:\Temp\Errorlogs"
$date = [DateTime]::Now.ToString("yyyyMM\\\\dd")
$pattern = '\\(?<folder>\w+)\\' + $date + '\\Error.*$'
$files = Get-ChildItem -Path $rootPath -Recurse | Select-Object -Property Fullname | Where-Object {$_.Fullname -Match $pattern}
foreach($file in $files)
{
$file.Fullname -match $pattern
Write-Host "folder = " $Matches.folder
}
Looks like you can do it just with splitting the path using \ as delimiter then picking the 3rd token (2nd index of an array):
$targetDir = "C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*" |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } |
Select-Object #{ N='Name'; E={ $_.FullName.Split('\')[2] }}
Another option if you want 2 levels up in the folder hierarchy is to query the .Directory property of the file then the .Parent property of the parent folder (2 times or as many times as needed):
$targetDir = "C:\Errorlogs"
Get-ChildItem $targetDir -Recurse -ErrorAction SilentlyContinue -Force -Filter "*Error*" |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } |
Select-Object #{ N='Name'; E={ $_.Directory.Parent.Parent.Name }}
As long as the subfolders inside the folder you are after all have numeric-only names, you can loop backwards to get at the first non-numeric foldername and output that.
$targetDir = "C:\Errorlogs"
Get-ChildItem -Path $targetDir -File -Filter "*Error*" -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { [datetime]::Now.Date -eq $_.LastWriteTime.Date } | ForEach-Object {
$parentDir = $_.Directory
while ($parentDir.Name -match '^\d+$') { $parentDir = $parentDir.Parent }
$parentDir.Name
}
That way, even a path C:\Errorlogs\AsyncCreateUsersAPIProcessor\202302\02\04\1234\567\Error.txt would produce folder name AsyncCreateUsersAPIProcessor
Can a wildcard be put in a folder name mask? Or is it necessary to run Get-ChildItem twice, one for the direcdtories and a second for the path? Even with the code below, I'm getting no directories returned.
I think this post shows how to do it with the older syntax:
$folderName = "c:\BizTalk\Vendors\*\AS2FilesReceived\"
$folderMask = "$folderName\*.*"
$dirs = Get-ChildItem -Path $folderName -Recurse -Directory
Write-Host "Number of Matching Directories = $($dirs.Count)"
$dirs
#$files = $dirs | %{ Get-ChildItem -Path $folderMask -Filter "*.*" -Exclude "*997*.*" -File} | Where-Object {$_.CreationTime -gt (Get-Date).AddDays(-6)} | Sort-Object LastWriteTime -Descending
Get-ChildItem supports wildcards in the path, but the wildcard applies only to a single folder level, i.e. a pattern C:\foo\*\bar will find folders C:\foo\abc\bar and C:\foo\xyz\bar, but won't find a folder C:\foo\abc\xyz\bar. For the latter you need something like this:
Get-ChildItem 'C:\foo' -Filter 'bar' -Directory -Recurse
If you have just a single variable folder level and want only files from the given path (without recursion) you can do something like this:
Get-ChildItem 'C:\foo\*\bar\*' -File
If you also want all files in subfolders below bar use this:
Get-ChildItem 'C:\foo\*\bar' -File -Recurse
Assuming that you want to find and return info about all files in all AS2FilesReceived directories for each folder under Vendors, then this might help you...
#Find all AS2FilesReceived directories
$dirs= Get-ChildItem -Path 'C:\BizTalk\Vendors\*\AS2FilesReceived\' -Directory
#Return number of directories
"$($dirs.Count) directories found"
#Return list of directory names
$dirs | % {$_.Parent.Name}
#Return the full name of every text file under each directory
$dirs | % {Get-ChildItem -Path $_ *.txt} | % {$_.FullName}
Which returns...
3 directories found
Vendor1
Vendor2
Vendor3
C:\BizTalk\Vendors\Vendor1\AS2FilesReceived\Vendor1AS2File.txt
C:\BizTalk\Vendors\Vendor2\AS2FilesReceived\Vendor2AS2File.txt
C:\BizTalk\Vendors\Vendor3\AS2FilesReceived\Vendor3AS2File.txt
Ultimately, I just wanted the files, not sure if I had a typo or what, but now this works. It's possible I swithced from $folderMask to $folderName, or didn't have the *.* on the end of the $folderMask.
$folderMask = "c:\BizTalk\Vendors\*\AS2FilesReceived\*.*"
$files = Get-ChildItem -Path $folderMask -File
Write-Host "Number of Matching Files = $($files.Count)"
I have a list of 350 folders and each folder has a file Access log. I need to search all 350 files under all 350 folders for a name "Hound" and display the name of the folders which contain the name "Hound" in their access log file.
Below is my code, can someone help me with what should be added here to get the desired output, please?
#List all the folders in C:\testfolder
$folders = (Get-ChildItem -Path "C:\testfolder" | Where-Object{$_.Attributes -eq "Directory"} | Select Fullname)
#looping all folders
Foreach ($folder in $folders)
{
#Here I need to look for the word "Hound" inside the Access.log file and if the word is there, it should display the name of the $folder which has the word
}
Here's a fairly basic way to do this:
Get-ChildItem -Path d:\testfolder -Recurse | Select-String -Pattern "Hound"
If you need to make sure that only files called access.log are searched then specify a filter:
Get-ChildItem -Path d:\testfolder -Include "access.log" -Recurse | Select-String -Pattern "Hound"
Does anybody know a powershell 2.0 command/script to count all folders and subfolders (recursive; no files) in a specific folder ( e.g. the number of all subfolders in C:\folder1\folder2)?
In addition I also need also the number of all "leaf"-folders. in other words, I only want to count folders, which don't have subolders.
In PowerShell 3.0 you can use the Directory switch:
(Get-ChildItem -Path <path> -Directory -Recurse -Force).Count
You can use get-childitem -recurse to get all the files and folders in the current folder.
Pipe that into Where-Object to filter it to only those files that are containers.
$files = get-childitem -Path c:\temp -recurse
$folders = $files | where-object { $_.PSIsContainer }
Write-Host $folders.Count
As a one-liner:
(get-childitem -Path c:\temp -recurse | where-object { $_.PSIsContainer }).Count
To answer the second part of your question, of getting the leaf folder count, just modify the where object clause to add a non-recursive search of each directory, getting only those that return a count of 0:
(dir -rec | where-object{$_.PSIsContainer -and ((dir $_.fullname | where-object{$_.PSIsContainer}).count -eq 0)}).Count
it looks a little cleaner if you can use powershell 3.0:
(dir -rec -directory | where-object{(dir $_.fullname -directory).count -eq 0}).count
Another option:
(ls -force -rec | measure -inp {$_.psiscontainer} -Sum).sum
This is a pretty good starting point:
(gci -force -recurse | where-object { $_.PSIsContainer }).Count
However, I suspect that this will include .zip files in the count. I'll test that and try to post an update...
EDIT: Have confirmed that zip files are not counted as containers. The above should be fine!
Get the path child items with recourse option, pipe it to filter only containers, pipe again to measure item count
((get-childitem -Path $the_path -recurse | where-object { $_.PSIsContainer }) | measure).Count
I would like to use power shell to loop all subfolders and run all the files in it. But, if my root contain 3 subfolders, I would like to loop and list it accordingly to the sequence where : Subfolder C , Subfolder B and Subfolder A so that the file execution will run according to the sequence ( C-->B-->A) .
Below is my coding.
Get-ChildItem -path "C:\Root\subfolders\" -recurse -Filter *.sql | foreach-object -process { $_.FullName }|
ForEach-Object {
sqlcmd -i $_
}
Give this a try, get all folders of C:\Root\subfolders and foreach folder found get its files recursively :
Get-ChildItem C:\Root\subfolders |
Where-Object {$_.PSIsContainer} |
Foreach-Object {Get-ChildItem $_.FullName -Recurse -Filter *.sql | Foreach-Object {sqlcmd -i $_.FullName} }