Need help to locate the files along with size - powershell

I wrote a script in powershell to locate the files in share drives which takes the names of files from a .txt file. The script is as below.
$Files= Get-Content lock.txt
foreach ($File in $Files) {
get-childitem -path Z:\lonmgb003_2 -Name $File -Recurse
}
Could someone help me with identifying size of file along with path. Thanks in advance.

The -Name parameter is a switch - it doesn't take an argument - and it causes Get-ChildItem to output just the file name and nothing else. The $File argument is instead being bound to the -Filter parameter.
Remove the -Name parameter and then use the Select-Object cmdlet to select just the path and size.
Since you have all the file names in an array already, you might as well use the -Include parameter to retrieve them all at once:
Get-ChildItem -Path Z:\lonmgb003_2 -Include $Files -Recurse |Select FullName,Length

You would need the Length and FullName properties of the files. You can do something like this.
$array= #()
$Files= Get-Content lock.txt
foreach ($File in $Files)
{
get-childitem -path Z:\lonmgb003_2 -Recurse | ?{$_.Name -like $File}
$obj = New-Object PSObject
$Size = [Math]::Round((Get-ChildItem -Recurse $_.FullName | Measure-Object Length -Sum -ErrorAction SilentlyContinue).Sum / 1MB, 2)
$obj | Add-Member -MemberType NoteProperty -Name "Path" $_.FullName
$obj | Add-Member -MemberType NoteProperty -Name "SizeinMB" $Size
$array +=$obj
}
$array | select Path, SizeinMB
What i have done is create a custom PS object that will store the FullName(precisely path) and Size of all the files. The use of -Name property doesn't help as it would just return you file name as a string and not the name as file (whose property you can use). Hence, a where-Object to match the file names in the text file. After your operation is done, the desired output is stored in an array named $array.

Related

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

Select FullName and add-content to File

I've got the following powershell line:
$items = Get-ChildItem -Path "C:\temp" -Filter "*ä*" -Recurse | Select FullName
I want to write those paths to a *.txt file:
foreach ($item in $items){
add-content -Path C:\temp\test.txt -Value $item -Force
}
Output in test.txt:
#{FullName=C:\temp\ä}
How can I only write the Value of FullName to the txt-file ?
For example:
echo $item
and Output in Console:
C:\temp\ä
Common gotcha with PowerShell. $items is not an array of FullNames but an object array with a fullname property. (Array assuming more that one item was returned.)
$items = Get-ChildItem -Path "C:\temp" -Filter "*ä*" -Recurse | Select -Expand FullName
or
# Requires PowerShell v3.0 or above
$items = (Get-ChildItem -Path "C:\temp" -Filter "*ä*" -Recurse).Fullname
You should be able to do this:
foreach ($item in $items){
add-content -Path C:\temp\test.txt -Value $item.FullName -Force
}
Here's a common way to find this bit of info:
Get-ChildItem | Get-Member
Or the same with shorthands:
dir | gm
This will list all properties, methods, etc for the objects returned from Get-ChildItem.

read multiple lines from text file and added it to registry

Very very new to PowerShell
First off all I'd like to give the scenario what I'm trying to do.
We have a SharePoint site and users can add their OneNote books to this SharePoint site. The URL's to the SharePoint site is now changing. So I'm exporting the registry entries to a text file, change the part of the path to the new one, and add the new URL's to the registry.
The problem I'm having is when I export the URL's (because of the way I'm exporting for sure) the text file has a string called "Value" and the URL's are under it.
So the first question is how do I write the values to a text file where only the values get written (in this case the URL's)
And second question is how do I write these changed values back to the registry?
Every URL is a new "string" and the names start with 1, 2, 3 and so on.
Thank you everyone for their time in advance.
# Create a new folder if not exist file
$Folder = "C:\backup"
if(-not(Test-Path $Folder)){
New-Item -Path $Folder -ItemType Directory
}
# Start Logging
Start-Transcript -Path "C:\backup\onenote.log"
#Set Variables
$OneNoteBooks = "C:\backup\onenotenotebooks.txt"
$NewPath = '//newpath.com/'
# Delete the existing file if exists
If (Test-Path $OneNoteBooks){Remove-Item $OneNoteBooks}
# Create a new text file
New-Item -Path $OneNoteBooks -ItemType File
# Exporting OneNote SharePoint Notebooks and Correcting them to the new URL
Write-Host "Exporting OneNote SharePoint Notebooks and Correcting them to the new URL"
Push-Location
Set-Location 'HKCU:\Software\Microsoft\Office\14.0\Onenote\opennotebooks'
Get-Item . | Select-Object -ExpandProperty Property | ForEach-Object {
New-Object PSobject -Property #{"property"=$_;
"Value" = (Get-ItemProperty -Path . -Name $_).$_}} | Format-Table Value -AutoSize | Out-File $OneNoteBooks
Pop-Location
$ReplaceURL = Get-Content -Path $OneNoteBooks
ForEach-Object{
$ReplaceURL -replace "`//.*?(`/)", $NewPath | Out-File $OneNoteBooks
}
# Add Changed URL's to the registry
ForEach-Object {
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name PowerShellPath -PropertyType String -Value $PSHome
# Stop Logging
Stop-Transcript
Where to start? How about with the fact that in your ForEach loop you create an object with two properties, and then use Format-Table (alias FT used), and select one of the two properties making the whole object pointless... instead just get and output the value that you want.
Get-Item . | Select-Object -ExpandProperty Property | ForEach-Object {Get-ItemProperty -Path . -Name $_).$_} | Out-File $OneNoteBooks
Or better yet, use the built in functions of the Item from your Get-Item to get and set your values in a ForEach loop. Try this out...
# Create a new folder if not exist file
$Folder = "C:\backup"
if(-not(Test-Path $Folder)){
New-Item -Path $Folder -ItemType Directory
}
# Start Logging
Start-Transcript -Path "C:\backup\onenote.log"
#Set Variables
$OneNoteBooks = "C:\backup\onenotenotebooks.txt"
$NewPath = '//newpath.com/'
$OldPath = '//oldpath.com/'
$SitesChangingMask = "$([regex]::escape("$oldpath"))(nibremv|finance|sites/procurement|Comm|Departments/NITAS|ro|nitd|cnibr|communities/sig)/?"
# Delete the existing file if exists
If (Test-Path $OneNoteBooks){Remove-Item $OneNoteBooks}
# Create a new text file
New-Item -Path $OneNoteBooks -ItemType File
# Exporting OneNote SharePoint Notebooks and Correcting them to the new URL
"Exporting OneNote SharePoint Notebooks and Correcting them to the new URL"
Push-Location
Set-Location 'HKCU:\Software\Microsoft\Office\14.0\Onenote\opennotebooks'
$OneNoteReg = Get-Item .
$OneNoteReg.Property | ForEach-Object {
$CurrentValue = $OneNoteReg.GetValue($_)
$NewValue = if($CurrentValue.ToString() -match $SitesChangingMask){$CurrentValue.ToString() -replace "$OldPath", $NewPath}else{$CurrentValue.ToString()}
Set-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\Onenote\opennotebooks' -Name $_ -Value $NewValue
[PSCustomObject][Ordered]#{
"Value Name"=$_
"Original Value"=$CurrentValue
"Updated Value"=$NewValue
}
} | FT -AutoSize | Out-File $OneNoteBooks
Pop-Location
# Stop Logging
Stop-Transcript
I also changed your RegEx pattern for your replace since the old one didn't seem right. For example, in HTTP://www.microsoft.com/powershell it would update that string to read http://www.microsoft.com//newsite.com/powershell and I don't think that was your intention.
When saving data to a file, skip using the Format commands. You could use a CSV file here instead:
Get-Item . | Select-Object -Exp Property | ForEach-Object {
New-Object PSCustomObject -Property #{"Property"=$_;"Value"=(Get-ItemProperty . -Name $_).$_}} |
Export-Csv $OneNoteBooks
Modify the file, then re-read it like so:
$props = Import-Csv $OneNoteBooks
Then you can access the property names and values like so:
$props.Property[0]
$props.Value[0]
..
Of course, you don't really need to go to a file to modify the values. You could do it in memory:
$props = Get-Item . | Select-Object -Exp Property | ForEach-Object {
New-Object PSCustomObject -Property #{"Property"=$_;"Value"=(Get-ItemProperty . -Name $_).$_}}
$props = $props | Foreach {$_.Value = $_.Value -replace 'pattern','replacement'}
If you would prefer to create a .reg file that you can then import try this:
"Windows Registry Editor Version 5.00`n" > c:\onenotebooks.reg
"[$($pwd.ProviderPath)]" >> c:\onenotebooks.reg
Get-Item . | Select-Object -Exp Property |
ForEach-Object { "`"$_`"=`"$((Get-ItemProperty . -Name $_).$_)`"" } >> c:\onenotebooks.reg
The problem is in this line of code.
"Value" = (Get-ItemProperty -Path . -Name $_).$_}} | Format-Table Value -AutoSize | Out-File $OneNoteBooks
I'd suggest removing the format-table. If its not showing you everything then try this:
"Value" = (Get-ItemProperty -Path . -Name $_).$_}} | Foreach-Object {$_.Value} | Out-File $OneNoteBooks

File and folder count

There is a folder on the remote server which has various subfolders in it. It is completely nested. I would like to:
Prepare an HTML report which contains folder name.
For every folder it should also record the file count.
The code needs to append the HTML file which is already created.
Columns required: Folder name, Folder Path, File Count
Below is the code snippet which is part of my main script. I am fairly new to PowerShell.
Can some one please help?
$server_dir = "D:\Data\Inbox"
$does_dir_e = (Test-Path $server_dir)
if($does_dir_e)
{
$fso = New-Object -com "Scripting.FileSystemObject"
$f = $fso.GetFolder($server_dir)
foreach($folder in $f.subfolders)
{
$fcount = $((Get-ChildItem $folder.Path).count)
$fname = $folder.name | Convertto-HTML -Fragment >> C:\Temp\Server.html
}
}
You don't actually say what isn't working for you, but the following script should get you started.
The outer loop recurses through the folders (PSIsContainer) means it is a folder.
The inner loop counts the number of files in each folder using measure-object, we filter out folders from this count to give us just the file count.
$path = "D:\Data\Inbox"
# Enumerate the given path recursively
Get-ChildItem -Path $path -Recurse | Where-Object {$_.PSIsContainer} | %{
# Add a user-defined custom member with a value of the filecount this
# time not recursively (using measure object)
$_ | add-member -membertype noteproperty -name FileCount -value (Get-ChildItem -Path $_.Fullname |
Where-Object {!$_.PSIsContainer} |
Measure-Object).Count
# Output the required values
$_ | select Name, FullName, FileCount | ConvertTo-Html -Fragment
}
Is this what you want? I haven't used the HTML cmdlet before, so be aware it's ugly : )
$server_dir = 'D:\Data\Inbox'
if(Test-Path $server_dir)
{
$folders = Get-ChildItem $server_dir -Recurse | where {$_.PSIsContainer}
$output = #()
foreach($folder in $folders)
{
$fname = $folder.Name
$fpath = $folder.FullName
$fcount = Get-ChildItem $fpath | where {!$_.PSIsContainer} | Measure-Object | Select-Object -Expand Count
$obj = New-Object psobject -Property #{FolderName = $fname; FolderPath = $fpath; FileCount = $fcount}
$output += $obj
}
#Output to HTML
$output | ConvertTo-Html -Fragment >> 'C:\Temp\Server.html'
}

How to Pipe Multiple Commands to CSV File [Powershell]

I'm trying to get The Folder Info and Security Info for all the folders on our server.
But I'm not to familiar with Powershell here. Mind helping a newbie?
How to do I get the Security acl piped into the Text file?
Along with just the member objects of Folder Name, Size, sub folder count?
# Step 1 Get Folder Path
function Select-Folder($message='Select a folder', $path = 0) {
$object = New-Object -comObject Shell.Application
$folder = $object.BrowseForFolder(0, $message, 0, $path)
if ($folder -ne $null) {
$folder.self.Path
}
}
#Step 2:Search For Directories
$dirToAudit = Get-ChildItem -Path (Select-Folder 'Select some folder!') -recurse | Where {$_.psIsContainer -eq $true}
foreach ($dir in $dirToAudit)
{
#Step 3: Output: [Folder Path, Name, Security Owner, Size, Folder Count]
#Pipe To CSV Text File
Get-Acl -Path $dir.FullName | Select-Object PSPath, Path,Owner | export-csv C:\temp\SecurityData.csv
#I also want the Folder path, Size and SubFolder Count
}
#Step 4: Open in Excel
invoke-item -path C:\temp\SecurityData.csv
Here's some sites that I found useful on the subject: http://blogs.msdn.com/b/powershell/archive/2007/03/07/why-can-t-i-pipe-format-table-to-export-csv-and-get-something-useful.aspx
http://www.maxtblog.com/2010/09/to-use-psobject-add-member-or-not/
This task isn't particularly easy. First you will want to create a custom object that contains the properties you want. These properties will be added via different commands e.g.:
$objs = Get-ChildItem . -r |
Where {$_.PSIsContainer} |
Foreach {new-object psobject -prop #{Path=$_.FullName;Name=$_.Name;FolderCount=$_.GetDirectories().Length}}
$objs = $objs | Foreach { Add-Member NoteProperty Owner ((Get-Acl $_.Path).Owner) -Inp $_ -PassThru}
$objs | Export-Csv C:\temp\data.csv
Getting the folder size will take some extra work to compute.