Windows Powershell: Display File Path along with Name and LastWriteTime - file

I'm using a Windows Powershell code that is very good but with one caveat. See below:
PS F:\Bizfi> dir -r | Out-GridView | Select FullName, LastWriteTime
The caveat is that it does not display the file path. Is there a way to include the file path within the name or as a separate property?
Thanks

If you want to mimic normal Get-ChildItem output:
dir -r | Select Mode,LastWriteTime,Length,Name,Fullname | Out-GridView

Related

Search Directory for folders

I am trying to create a batch file that I can use to type in a name of a folder and search multiple directories, then display the results in a new window. Example: I want to search for "tcash" in 3 separate directories, ie; \vm-xa01\users, vm-xa02\users and vm-xa03\users. How can I do this?
The original question had Powershell tag, so the answer is Powershell. For cmd (batch) script, I'd strongly suggest you to move into Powershell anyway. It's 2018 and cmd scripts require lots of tweaking.
In Powershell, there's a built-in cmdlet Out-GridView that might be suitable. For example, to display all txt files in c:\some\path and its subdirectories requires just a few commands. Like so,
gci c:\some\path -Recurse | ? { $_.extension -eq ".txt" } | ogv
First off, get a recursive list of all files
gci c:\some\path -Recurse
Then select those that have extension .txt
| ? { $_.extension -eq ".txt" }
Finally, pass the results to out-gridview aka ogv
| ogv
I also think PowerShell is the better script language for your task.
You can do a dir/Get-ChildItem with ranges [1-3] similar to a Regular Expression, so:
Get-ChildItem "\vm-xa0[1-3]\users\tcash" -File -Recurse | Out-Gridview
should enumerate all matching files and display in a gui window.

Search a literal in a zip file

I have a folder with oracle bi publisher reports
Folder/Usage Trend Report.xdmz
Folder/Usage Summary Report.xdmz
Folder/Charge Trend Report.xdmz
Folder/Consolidation Reports.xdmz
Folder/Charge Summary Report.xdmz
Each report is like zip file and contains some files
_datamodel.xdm
~metadata.meta
security.xml
I want to make a batch file, searches all the _datamodel.xdm file in order to find a literal (eg INVOICE_NBR or invoice_nbr)
The output will be something like
Report Name Literal Usages
Consolidation Reports.xdmz INVOICE_NBR 1
Is there anyone to help me do it ?
Thanks
In the future, please show what you've tried to solve the problem on your own, and where you're getting stuck. For this time, I found the challenge interesting, so I whipped up a beginning for you. It's a Batch + PowerShell hybrid script. Save it with a .bat extension and salt to taste. Be advised that the regexp object that performs a count of strings uses case-sensitive matching; so "INVOICE_NBR" would not increment the count when searching for "invoice_nbr".
<# : batch portion
#echo off & setlocal
set "outerfile=*.xdmz"
set "innerfile=_datamodel.xdm"
set "search=invoice_nbr"
rem // re-launch self with PowerShell interpreter
powershell "iex (${%~f0} | out-string)"
goto :EOF
: end batch / begin PowerShell hybrid chimera #>
add-type -as System.IO.Compression.FileSystem
# // encapsulate loop into a collection for select | format-table
&{ foreach ($archive in (gci $env:outerfile)) {
# // create a temporary directory within %temp%
$tempdir = New-Item -path $env:temp -name ([Guid]::NewGuid()) -type dir
[IO.Compression.ZipFile]::ExtractToDirectory($archive, $tempdir)
# // For each innerfile found within the zip archive...
gci -path $tempdir -filter $env:innerfile -recurse | %{
new-object PSObject -property #{
"Report Name" = $archive.Name
"Usages" = ([regex]::Matches((gc $_.FullName | out-string), $env:search)).count
"Literal" = $env:search
}
}
Remove-Item $tempdir -recurse -force
} } | select "Report Name",Literal,Usages | format-table -auto
Example output:
Report Name Literal Usages
----------- ------- ------
Usage Summary Report.xdmz invoice_nbr 2
Usage Trend Report.xdmz invoice_nbr 2
If you want case-insensitive matching, add the following as a third argument to the [regex]::Matches() function:
[Text.RegularExpressions.RegexOptions]::IgnoreCase

How to save Filename and Modified Date to .txt filein PowerShell v3.0

I am trying to convert my batch file syntax to PowerShell v3.0. I need to pull all the file names from a mapped network drive and save it to a folder on my root C:
Everything works except when it comes to saving the file names. If I do
dir /s > C:\2\filename.txt
In a batch file it will output the file's name (along with the extension) and the date modified to a .txt file. However I cannot get the PowerShell v3.0 equvalent to work. It just creates a txt file but nothing is saved within the file. Here is my PowerShell v3.0 code.
Get-ChildItem -Path K:\Transactions\Processed\Audit-Images\Lane` 12\$date\done > C:\2\$date-LaneServer12ImagesDONE.txt
In the examples below, you may want to add some parameters to Get-ChildItem depending on what you're looking for. "-Force" to have it list hidden files, "-Attributes !Directory" to exclude directory names.
I would find the output most useful in a csv.
Get-ChildItem -Path K:\Transactions\Processed\Audit-Images\Lane` 12\$date\done -Recurse | Select-Object Name,LastWriteTime | Export-CSV "C:\2\filename.csv"
Same line, in a text file:
Get-ChildItem -Path K:\Transactions\Processed\Audit-Images\Lane` 12\$date\done -Recurse | Select-Object #{n='File';e={$_.Name + " " + $_.LastWriteTime}} | Out-File "C:\2\filename.txt"

How to copy *.csv to one txt file in same directory? Using PowerShell

In C:Temp I have 5 csv files, how I copy all to one file.txt?
Thanks
Josef
If you know the names, you can get the content like this:
Get-Content c:\item1.csv, c:\item2.csv
# or
Get-Content c:\*.csv
The Get-Content command will read all the specified files and return it as array of strings. Note that you can specify encoding as well.
Get-Content -Encoding Utf8 c:\*.csv
(for more info see Get-Help Get-Content -online or help gc -online)
As for storing the content to the file, pipe the otput from Get-Content to Set-Content. You can specify encoding as well. I'm saying that because redirection (>) by default outputs the content as Unicode, which is not always wanted.
Long story short. Use:
Get-Content *.csv | Set-Content file.txt
You can of course use build-in cmdlets for working with CSV. First list the files and pipe to Import-Csv. This will produce an PsObject for each csv row. This is piped to Export-CSv to store it in a file:
Get-Item c:\csv1.csv, c:\csv2.csv |
Import-Csv |
Export-Csv c:\res.txt
cat *.csv > yourtxtfilename.txt
If you're just going to use the command prompt, replace cat with type.
The wildcard expansion order is undefined, so if the order is important you can specify it explicitly with:
cat file1.csv, file2.csv, file3.csv, file4.csv, file5.csv > file1-5.csv
cat is an alias for Get-Content

Get file version in PowerShell

How can you get the version information from a .dll or .exe file in PowerShell?
I am specifically interested in File Version, though other version information (that is, Company, Language, Product Name, etc.) would be helpful as well.
Since PowerShell 5 in Windows 10, you can look at FileVersionRaw (or ProductVersionRaw) on the output of Get-Item or Get-ChildItem, like this:
(Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.FileVersionRaw
It's actually the same ScriptProperty from my Update-TypeData in the original answer below, but built-in now.
In PowerShell 4, you could get the FileVersionInfo from Get-Item or Get-ChildItem, but it would show the original FileVersion from the shipped product, and not the updated version. For instance:
(Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.FileVersion
Interestingly, you could get the updated (patched) ProductVersion by using this:
(Get-Command C:\Windows\System32\Lsasrv.dll).Version
The distinction I'm making between "original" and "patched" is basically due to the way the FileVersion is calculated (see the docs here). Basically ever since Vista, the Windows API GetFileVersionInfo is querying part of the version information from the language neutral file (exe/dll) and the non-fixed part from a language-specific mui file (which isn't updated every time the files change).
So with a file like lsasrv (which got replaced due to security problems in SSL/TLS/RDS in November 2014) the versions reported by these two commands (at least for a while after that date) were different, and the second one is the more "correct" version.
However, although it's correct in LSASrv, it's possible for the ProductVersion and FileVersion to be different (it's common, in fact). So the only way to get the updated Fileversion straight from the assembly file is to build it up yourself from the parts, something like this:
Get-Item C:\Windows\System32\Lsasrv.dll | ft FileName, File*Part
Or by pulling the data from this:
[System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName)
You can easily add this to all FileInfo objects by updating the TypeData in PowerShell:
Update-TypeData -TypeName System.IO.FileInfo -MemberName FileVersionRaw -MemberType ScriptProperty -Value {
[System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName) | % {
[Version](($_.FileMajorPart, $_.FileMinorPart, $_.FileBuildPart, $_.FilePrivatePart)-join".")
}
}
Now every time you do Get-ChildItem or Get-Item you'll have a FileVersionRaw property that shows the updated File Version ...
Since PowerShell can call .NET classes, you could do the following:
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("somefilepath").FileVersion
Or as noted here on a list of files:
get-childitem * -include *.dll,*.exe | foreach-object { "{0}`t{1}" -f $_.Name, [System.Diagnostics.FileVersionInfo]::GetVersionInfo($_).FileVersion }
Or even nicer as a script: https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-information/
'dir' is an alias for Get-ChildItem which will return back a System.IO.FileInfo class when you're calling it from the filesystem which has VersionInfo as a property. So ...
To get the version info of a single file do this:
PS C:\Windows> (dir .\write.exe).VersionInfo | fl
OriginalFilename : write
FileDescription : Windows Write
ProductName : Microsoft® Windows® Operating System
Comments :
CompanyName : Microsoft Corporation
FileName : C:\Windows\write.exe
FileVersion : 6.1.7600.16385 (win7_rtm.090713-1255)
ProductVersion : 6.1.7600.16385
IsDebug : False
IsPatched : False
IsPreRelease : False
IsPrivateBuild : False
IsSpecialBuild : False
Language : English (United States)
LegalCopyright : © Microsoft Corporation. All rights reserved.
LegalTrademarks :
PrivateBuild :
SpecialBuild :
For multiple files this:
PS C:\Windows> dir *.exe | %{ $_.VersionInfo }
ProductVersion FileVersion FileName
-------------- ----------- --------
6.1.7600.16385 6.1.7600.1638... C:\Windows\bfsvc.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\explorer.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\fveupdate.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\HelpPane.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\hh.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\notepad.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\regedit.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\splwow64.exe
1,7,0,0 1,7,0,0 C:\Windows\twunk_16.exe
1,7,1,0 1,7,1,0 C:\Windows\twunk_32.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\winhlp32.exe
6.1.7600.16385 6.1.7600.1638... C:\Windows\write.exe
I realise this has already been answered, but if anyone's interested in typing fewer characters, I believe this is the shortest way of writing this in PS v3+:
ls application.exe | % versioninfo
ls is an alias for Get-ChildItem
% is an alias for ForEach-Object
versioninfo here is a shorthand way of writing {$_.VersionInfo}
The benefit of using ls in this way is that you can easily adapt it to look for a given file within subfolders. For example, the following command will return version info for all files called application.exe within subfolders:
ls application.exe -r | % versioninfo
-r is an alias for -Recurse
You can further refine this by adding -ea silentlycontinue to ignore things like permission errors in folders you can't search:
ls application.exe -r -ea silentlycontinue | % versioninfo
-ea is an alias for -ErrorAction
Finally, if you are getting ellipses (...) in your results, you can append | fl to return the information in a different format. This returns much more detail, although formatted in a list, rather that on one line per result:
ls application.exe -r -ea silentlycontinue | % versioninfo | fl
fl is an alias for Format-List
I realise this is very similar to xcud's reply in that ls and dir are both aliases for Get-ChildItem. But I'm hoping my "shortest" method will help someone.
The final example could be written in long-hand in the following way:
Get-ChildItem -Filter application.exe -Recurse -ErrorAction SilentlyContinue | ForEach-Object {$_.VersionInfo} | Format-List
... but I think my way is cooler and, for some, easier to remember. (But mostly cooler).
I prefer to install the PowerShell Community Extensions and just use the Get-FileVersionInfo function that it provides.
Like so:
Get-FileVersionInfo MyAssembly.dll
with output like:
ProductVersion FileVersion FileName
-------------- ----------- --------
1.0.2907.18095 1.0.2907.18095 C:\Path\To\MyAssembly.dll
I've used it against an entire directory of assemblies with great success.
Just another way to do it is to use the built-in file access technique:
(get-item .\filename.exe).VersionInfo | FL
You can also get any particular property off the VersionInfo, thus:
(get-item .\filename.exe).VersionInfo.FileVersion
This is quite close to the dir technique.
This is based on the other answers, but is exactly what I was after:
(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("Path\To\File.dll")
I find this useful:
function Get-Version($filePath)
{
$name = #{Name="Name";Expression= {split-path -leaf $_.FileName}}
$path = #{Name="Path";Expression= {split-path $_.FileName}}
dir -recurse -path $filePath | % { if ($_.Name -match "(.*dll|.*exe)$") {$_.VersionInfo}} | select FileVersion, $name, $path
}
As EBGreen said, [System.Diagnostics.FileVersionInfo]::GetVersionInfo(path) will work, but remember that you can also get all the members of FileVersionInfo, for example:
[System.Diagnostics.FileVersionInfo]::GetVersionInfo(path).CompanyName
You should be able to use every member of FileVersionInfo documented here, which will get you basically anything you could ever want about the file.
Here an alternative method. It uses Get-WmiObject CIM_DATAFILE to select the version.
(Get-WmiObject -Class CIM_DataFile -Filter "Name='C:\\Windows\\explorer.exe'" | Select-Object Version).Version

Resources