Save directory tree to CSV, along with whether element is a file or folder in powershell - powershell

So far I've got this:
Get-ChildItem -Recurse 'C:\MyFolder' |
Select-Object FullName, name |
Export-Csv -path 'C:\output.csv' -noTypeInfo
It gives me a CSV with the full path name, and name of each folder & file in a directory.
However, I'd like a 3rd column that has either 'Folder' or 'File' (or something similar). Basically just a column that explicitly tells me whether something is a file or folder.
I feel like it should be a simple case of adding a new column like FullName, name, Type - but not sure what options are available.
Is this possible?

You could use the Attributes property however, this might give you more information than you really need, see FileAttributes Enum.
If you simply need a property with 2 values (File or Directory) you can use the boolean property PSIsContainer as reference to construct your new calculated property:
Get-ChildItem -Recurse 'C:\MyFolder' |
Select-Object FullName, Name, #{N='Type';E={('File', 'Directory')[$_.PSIsContainer]}} |
Export-Csv -path 'C:\output.csv' -NoTypeInformation

Related

How to use Get-Content to get all information from the most recent file

I am trying to use Get-Content to get the most recent .xml file and all its content to be displayed in the powershell window, but I am having a hard time.
I have use the the following:
Get-ChildItem "\\Server1\c$\Program Files\AAA\Logs\" | Sort-Object CreationTime | Select-Object -Last 1
Get-Content -Path "\\Server1\c$\Program Files\AAA\Logs\" | Where-Object {$_.LastWriteTime -lt (get-date).addDays(-1)} | Select -Last 1
But I cannot figure out how to go about grabbing the latest file and displaying all its content in the console
You are close. You have to pipe the result of your first line to Get-Content:
Get-ChildItem "\\Server1\c$\Program Files\AAA\Logs\" | Sort-Object CreationTime | Select-Object -Last 1 | Get-Content
Your second line does not make much sense. If you provide a valid path to Get-Content, it will return to you the content of the file as a string. You cannot apply any creation time logic to this content afterwards with Where-Object.
Your first line though, works like this:
It gets all files and folders that are contained in your given path. If this path really just contains valid log files, you can leave it like this. Otherwise you should filter this result, so you really just get your desired files. To be precise, Get-ChildItem returns an array of System.IO.FileInfo objects. They contain a lot of information about your files.
You then sort this array of System.IO.FileInfo objects by the CreationTime property with Sort-Object.
Finally, you select the last element of the sorted array. This is still a System.IO.FileInfo object. That's why you see some of its properties in your output.
If you then pipe this System.IO.FileInfo object to Get-Content, the FullPath property of this object will be mapped to the -Path parameter of Get-Content, thus returning the content of the file specified by the System.IO.FileInfo object.

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

PowerShell Get-Childitem changes output

Noticed some weird behaviour with PowerShell Get-ChildItem. I do something like this in my script:
New-PSDrive -Name "R" -PSProvider "FileSystem"-Root "\\server\share"
$files = Get-ChildItem "R:/" | Select-Object -Property * -ExcludeProperty VersionInfo
$files | export-csv -Path "output.csv" -Delimiter ";"
The Get-ChildItem returns an object with properties such as BaseName, FullName, Parent, Root, ...
The problem I am having is that recently (or on some network shares which I mount) the properties of the object returned by Get-ChildItem changed. It used to be this list:
PSPath PSParentPath PSChildName PSDrive PSProvider PSIsContainer Mode BaseName Target LinkType Name FullName Parent Exists Root Extension CreationTime CreationTimeUtc LastAccessTime LastAccessTimeUtc LastWriteTime LastWriteTimeUtc Attributes
and as of recent (or as mentioned, for certain shared folder, haven't figured that out yet) the following properties were added:
Length DirectoryName Directory
In my CSV I now have 3 extra columns in between Name and IsReadOnly the aforementioned 3 properties are added. Does anyone know if this is due to an update of PowerShell or due to the specific server for which the shared folder was mounted?
As pointed out by #AdminOfThings, Get-ChildItem can return multiple object types: DirectoryInfo and FileInfo where only FileInfo has the properties Directory, DirectoryName and Length. Therefore, when exporting the results from Get-ChildItemto a CSV file. This file will only contain the 3 columns if the folder also contained files.
The following documentation describes the behaviour of export-csv in case you submit multiple object with different types Microsoft Powershell6.0:
When you submit multiple objects to Export-CSV, Export-CSV organizes the file based on the properties of the first object that you submit. If the remaining objects do not have one of the specified properties, the property value of that object is null, as represented by two consecutive commas. If the remaining objects have additional properties, those property values are not included in the file.
I will update the answer once I found a solution to make the CSV output consistent.

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