How to search a files in multiple folders that returns no duplicate in powershell? - powershell

I am trying to find all the files in the multiple folders but the only thing is that the files existed in some folders
E:\sample\cd.dll
E:\sample1\sample\cd.dll
If I am using the
Get-ChildItem -recurse
it returns Two FileSystemInfo of cd.dll.
The result should be only one FileName of cd.dll
thanks in advance.

Get-ChiltItem -recurse | Select-Object -Unique
Note that -Unique is case-sensitive so you may want to use the Sort-Object cmdlet:
Get-ChiltItem -recurse | Sort-Object -Unique
You can also eliminates duplicates with the Get-Unique cmdlet but it requires the objects to be sorted first for the cmdlet to work properly

Related

Powershell Folder List Filter

I have a folder and inside has a list of subfolders/files
Folders
2022
20221101
20221103
20221107
20221108
test123
results
test.txt
Using Powershell
How do get the list of folders that are dates.
How do I get the second latest folder (20221107).
This is what I was able to come with so far:
Get-ChildItem "C:\code\Test" -Filter "2022*" | Sort-Object Name -Descending
You can use TryParseExact method from DateTime to parse the folders names and avoid any type of error, this can be combined with Sort-Object and Select-Object to get the 2nd latest. I have added -Directory to output only folders. Also changed your filter to -Filter "2022????" to ensure you're matching folders that start with 2022 and are followed by 4 characters.
$ref = [ref] [datetime]::new(0)
Get-ChildItem "C:\code\Test" -Filter "2022????" -Directory | Sort-Object {
$result = [datetime]::TryParseExact(
$_.Name,
'yyyyMMdd',
[cultureinfo]::InvariantCulture,
[Globalization.DateTimeStyles]::AssumeLocal,
$ref
)
if($result) { $ref.Value }
} -Descending | Select-Object -Index 1
If you want to ensure you're matching folders with a date format (because -Filter may be too permissive), you can pipe to Where-Object for additional filtering via regex:
$ref = [ref] [datetime]::new(0)
Get-ChildItem "C:\code\Test" -Filter "2022????" -Directory |
Where-Object Name -Match '^2022\d{4}$' | Sort-Object {
# rest of the code here
} -Descending | Select-Object -Index 1
To provide an alternative to Santiago's helpful answer:
Since the timestamps that your folder names represent sort lexically in a way that is equivalent to their chronological sorting, you may not need to convert them to [datetime] instances, and can sort them as-is.
Get-Item C:\code\Test\* -Include 2022???? |
Sort-Object Name -Descending |
Select-Object -Index 1
Note the use of -Include instead of -Filter (which in turn necessitates ending the -Path argument with \* and using Get-Item instead of Get-ChildItem), because the -Filter parameter has legacy quirks that prevent character-exact matching with multiple ? wildcards - see this answer for background information.
Unfortunately, as this solution and the linked answer shows, making -Include (and -Exclude) work as intended is tricky as of PowerShell 7.2.x, and requires memorizing non-intuitive rules.
On the plus side, -Include, which (unlike -Filter) uses PowerShell's wildcard expressions, would also allow you to create a more specific pattern, such as -Include 2020[0-1][0-9][0-3][0-9] (which still isn't strict enough to rule out invalid digit combinations, however).

Powershell - using dir / GetChildItem to list directories with Date Modified

So currently I am able to get a list of my directories with the folder name using
dir -directory -name
And I also know I can use recurse as well to list sub-directories
Thank you to Sany
What I would like to create in this list is to show this folder's date modified value. I've looked over the documentation and I'm having difficulty to find the answer I assume if it is there it is likely part of Attributes but I'm uncertain as to how to format it correctly.
Most of the searches I've done are have turned up about excluding files based on date modified, rather than showing the date instead.
You can use Select-Object and what I like to use Export-Csv
Get-ChildItem C:/temp -directory -recurse | Select-Object FullName, LastWriteTime | Export-Csv -Path list_my_folders.csv -NoTypeInformation
In case you want extract other information as well you can also remove the Select-Object part and you will see all columns which you can select.
Output:
"FullName","LastWriteTime"
"C:\temp\save","21.11.2019 15:34:27"
"C:\temp\test","12.01.2020 05:13:24"
"C:\temp\test\002custom","14.12.2019 01:17:54"
"C:\temp\test\002normal","14.12.2019 01:31:46"
"C:\temp\test\x","13.01.2020 12:51:05"
"C:\temp\test\002normal\normal","14.12.2019 01:31:53"
"C:\temp\test\x\Neuer Ordner","13.01.2020 12:51:05"
Of course you can also use it without Export-Csv:
Get-ChildItem C:/temp -directory -recurse | Select-Object FullName, LastWriteTime > list_my_folders.txt
But the output is in a format that is harder to work in most cases:
FullName LastWriteTime
-------- -------------
C:\temp\save 21.11.2019 15:34:27
C:\temp\test 12.01.2020 05:13:24
C:\temp\test\002custom 14.12.2019 01:17:54
C:\temp\test\002normal 14.12.2019 01:31:46
C:\temp\test\x 13.01.2020 12:51:05
C:\temp\test\002normal\normal 14.12.2019 01:31:53
C:\temp\test\x\Neuer Ordner 13.01.2020 12:51:05

How can I use PowerShell or a cmd "dir" to get the contents of multiple, but similar paths?

For example, I want the contents of the "Last" folder in the structure below. The various path structures are identical except for the first two levels.
C:\zyx-wvu\abc\Level3\Last
C:\tsr-qpo\def\Level3\Last
C:\nml-kji\ghi\Level3\Last
In PowerShell I get close with:
Get-ChildItem -Path C:\*-*\*
...but it doesn't return any results (as in it never finishes) when I try:
Get-ChildItem -Path C:\*-*\*\Level3
Get-ChildItem -Path C:\*-*\*
will only show you what's in the second layer behind anything with a hyphen in c:\
aka it will show
c:\1-2\alpha
c:\1-5\beta
etc...
What you want is
Get-ChildItem -Path C:\*-*\*\*
or more likely you want
Get-ChildItem -Path C:\*-*\* -recurse
if you want to find paths with the SAME name... you could group them together, and pull out anything with more than one finding... you didn't ask very specifically what you wanted, but here's some ideas.
get-childitem -Path c:\*-*\*\* | group-object -property basename | where count -gt 1 | select -expand group

Count Files by Name

I am looking for a way to count files from many sub-folders but the tricky part is that i want to filter them by part of their names. To be more specific, all files have a date at the middle of their names. If I want to just count the files within a specific folder I use this:
dir * |%{$_.Name.SubString(7,8)} | group |select name,count|ft -auto
And works like a charm. The problem lies that it cannot see more than one folder. Also a second problem is that in the result, I want to see the path name of the grouped counts. I am also testing this:
dir -recurse | ?{ $_.PSIsContainer } | %{ Write-Host $_.FullName (dir $_.FullName | Measure-Object).Count }
but I cannot implement the date filter from inside the name in this functions. I am also attaching an example of how is the format and how I would like the results.
Any help?
I am looking for a way to count files from many sub-folders but the tricky part is that I want to filter them by part of their names. To be more specific, all files have a date at the middle of their names.
It is not 100% clear to me, if you really want to filter them or to group them before counting, so I'll show both.
Assuming that this middle of their names is, e.g., delimited by _ this can be achieved the following way:
# C:/temp/testFolder/myName_123_folder/text.txt
Get-ChildItem * -Recurse |
Select-Object -Property Name, #{Name = "CustomDate"; Expression = {$_.Name.Split("_")[1]}} |
#This is how you would _filter_
#Where-Object {$_.Custom -eq "123"} |
Group-Object -Property CustomDate |
Select-Object Name, Count
Don't forget to check if the file name matches this pattern, before splitting. This can be done with a Select-Object statement between gci and 1. select, which checks the file name for your specific pattern.
Your question shows also that you wanted to filter for only directories:
dir -recurse | ?{ $_.PSIsContainer } | %{ #[...]
Which is not very efficient.
From the Docs of Get-ChildItem:
-Directory
Gets directories (folders).
To get only directories, use the -Directory parameter and omit the -File parameter. To exclude directories, use the -File parameter and omit the -Directory parameter, or use the -Attributes parameter.
This means, the preferred way to search only for Directories is:
Get-ChildItem -Recurse -Directory | % { #[...]

Run a function on each element of a list in powershell

I have a directory full of file pairs. Each pair of files have the same name with the extensions of mp3 and cdg (karaoke files!). I would like to use powershell to get the list of all distinct file names with no extensions
I've gotten as far as:
dir -recurse -filter "*.mp3" | select-object Name | sort
But I can't quite figure out how to pass each Name to [System.IO.Path]::GetFileNameWithoutExtension
how would I do this?
What you're looking for is the for-each (%) filter (not precisely sure if it's a filter or a cmdlet but it has the same usage syntax).
Try the following
dir -recurse -filter "*.mp3" |
%{ $_.Name } |
%{ [IO::Path]::GetFileNameWithoutExtension($_) } |
sort
EDIT Update
I changed my answer from "select-object Name" to "%{ $_.Name}". The former essentially takes the Name property off of the pipeline value and creates a new object with a single property of the specified name with the value on the original object. The latter will process every value in the pipeline and pass the result of executing $_.Name down the pipeline.
dir -recurse -filter "*.mp3"| select #{name='Name';Expression={[System.IO.Path]::GetFileNameWithoutExtension($_.Name)}} | sort
If you hate typing %{$_.foo} all the time like I do, try Get-PropertyValue (alias: gpv) from PSCX.
More musings here for the suitably geeky: http://richardberg.net/blog/?p=55
Now that PowerShell v2 is RTMd, you can select the BaseName member:
dir -recurse -filter *.mp3 | select BaseName | sort