Powershell, trying to output only the path and lastwritetime on directories - powershell

I am trying to write a script that will output any directory that has not changed in over 90 days. I want the script to only show the entire path name and lastwritetime. The script that I wrote only shows the path name but not the lastwritetime. Below is the script.
Get-ChildItem | Where {$_.mode -match "d"} | Get-Acl |
Format-Table #{Label="Path";Expression={Convert-Path $_.Path}},lastwritetime
When I run this script, I get the following output:
Path lastwritetime
---- ----------
C:\69a0b021087f270e1f5c
C:\7ae3c67c5753d5a4599b1a
C:\cf
C:\compaq
C:\CPQSYSTEM
C:\Documents and Settings
C:\downloads
I discovered that the get-acl command does not have lastwritetime as a member. So how can I get the needed output for only the path and lastwritetime?

You don't need to use Get-Acl and for perf use $_.PSIsContainer instead of using a regex match on the Mode property. Try this instead:
Get-ChildItem -Recurse -Force |
? {$_.PSIsContainer -and ($_.LastWriteTime -lt (get-date).AddDays(-90))} |
Format-Table FullName,LastWriteTime -auto
You may also want to use -Force to list hidden/system dirs. To output this data to a file, you have several options:
Get-ChildItem -Recurse -Force |
? {$_.PSIsContainer -and ($_.LastWriteTime -lt (get-date).AddDays(-90))} |
Select LastWriteTime,FullName | Export-Csv foo.txt
If you are not interested in CSV format try this:
Get-ChildItem -Recurse -Force |
? {$_.PSIsContainer -and ($_.LastWriteTime -lt (get-date).AddDays(-90))} |
Foreach { "{0,23} {1}" -f $_.LastWriteTime,$_.FullName} > foo.txt
Also try using Get-Member to see what properties are on files & dirs e.g.:
Get-ChildItem $Home | Get-Member
And to see all values do this:
Get-ChildItem $Home | Format-List * -force

Related

How to get the directory location for file recently modified

Suppose we have two directories C:\username\test1 & C:\username\test2. Both directories contain same file script.ps1. Now with powershell script I want to search the file script.ps1 in both directories & want the complete file location of file which is latest modified/created.
I was using below command but it did not give the desired output
Get-ChildItem -Path "C:\username" script.ps1 -Recurse | Where-object {!$_.psIsContainer -eq $true} | ForEach-Object -Process {$_.FullName} | select -last 1
For a given directory you can use
Get-ChildItem C:\dir1\dir2 -Recurse -ErrorAction SilentlyContinue | Where {!$_.PsIsContainer}|select Name,DirctoryName, LastWriteTime |Sort LastWriteTime -descending | select -first 1   Name DirctoryName LastWriteTime
And if you want it to run for multiple directories, you will have to run a loop on each directory:
Get-ChildItem C:\dir\* | Where {$_.PsIsContainer} | foreach-object { Get-ChildItem $_ -Recurse -ErrorAction Sile   ntlyContinue | Where {!$_.PsIsContainer} | Select Name,DirectoryName, LastWriteTime, Mode | Sort LastWriteTime -descend   ing | select -first 1}
It will list files which are last modified for each directories.
Edit: Search for a file
You can use following command to search for a file recursively if it is there in multiple directories:
Get-ChildItem -Path C:\Myfolder -Filter file.whatever -Recurse -ErrorAction SilentlyContinue -Force
This will list all versions of the file found, from newest to oldest:
Get-ChildItem -Path "C:\UserName" `
-File `
-Recurse `
-Include "Script.ps1" |
Sort-Object LastWriteTime -Descending |
Format-Table LastWriteTime, FullName -AutoSize
If you only want the most recent one, then replace the Format-Table line with:
Select-Object -First 1

Finding Files in a directory equal to 0 Powershell

I was wondering how I can display a list of empty files in a directory
$test = gci "C:\Users\Freedom\Documents" -Recurse
$test | Where-Object {$_.PsISContainer} | Select-Object FullName | Where-Object {$_.GetFiles() -eq 0}
I Don't understand because when I do get-childitem | get-member I get a list of properties and methods I can use and in the list is getfiles() why can't I use this method why's it giving me an error message?
Method invocation failed because [System.IO.FileInfo] does not contain a method named 'GetFiles'.
I think you want this:
Get-ChildItem | Where-Object { (-not $_.PSIsContainer) -and ($_.Length -eq 0) }
If you have PowerShell 3.0 or later you can use this:
Get-ChildItem -File | Where-Object { $_.Length -eq 0 }
Of course you can add whatever other parameters for Get-ChildItem that you want (-Recurse, etc.).
Wow I had what I wanted mixed up! And I had to add the .count to the getfiles() method
$test | Where-Object {$_.PsISContainer} | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName
try this
Get-ChildItem "c:\temp" -File -Recurse | where Length -eq 0
Use Get-ChildItem and the File flag, -Recurse is needed to get every file in the folder and in the folder below. Then get all the files were Get-Content returns null.
Get-ChildItem $YourPath -Recurse -File | Where-Object {!(Get-Content $_.Fullname)}

Powershell find folders, delete files leaving latest 5

We use software called Revit, files are saved as such: filename.rvt
Each time a user edits a file, Revit takes it upon itself to save the old file in the format filename.xxxx.rvt (where xxx is a number).
Over time when files are edited hundreds of times, we have many unnecessary files on the file server.
I am writing a script to:
Locate and folders containing Revit backup files
Delete all but the most recently modified 5 revit backup files
I have tried two approaches below
$searchpath = "e:\"
# Find a unique list of directories that contains a revit backup file (*.*.rvt)
$a = Get-ChildItem -Path $searchpath -Include *.*.rvt -Recurse | Select-object Directory -expandproperty FullName | Get-Unique -AsString
# For each folder that contains a single revit backup file (*.*.rvt)...
# - Sort by modified time
# - Select all except first 5
$a | Get-ChildItem -Include *.*.rvt | Sort-Object LastWriteTime -descending | select-object -skip 5 -property Directory,Name,CreationTime,LastWriteTime | Out-GridView -Title "Old Backups" -PassThru
The issue with this approach is that it only "skips" the first 5 files in the entire search result, not 5 in each folder.
Then I went about it using a loop, and this gets nowhere:
$searchpath = "e:\"
# Find a unique list of directories that contains a revit backup file (*.*.rvt)
$a = Get-ChildItem -Path $searchpath -Include *.*.rvt -Recurse | Select Directory | Get-Unique -AsString
# For each folder that contains a single revit backup file (*.*.rvt)...
# - Sort by modified time
# - Select all except first 5
$a | foreach {
$b += Get-ChildItem -Path $_.Directory.FullName -Include *.*.rvt | Sort-Object LastWriteTime -descending | select-object -skip 5 -property Directory,Name,CreationTime,LastWriteTime
}
$b | Out-GridView -Title "Old Backups" -PassThru
Any thoughts on the correct approach and whats going wrong?
try this:
get-childitem -file -recurse | group Directory | where Count -gt 5 | %{
$_.Group | Sort LastWriteTime -descending | select -skip 5 Directory,Name,CreationTime,LastWriteTime
} | Out-GridView -Title "Old Backups"
If you want delete you can do it (remove what if)
gci -file -recurse | group Directory | where Count -gt 5 | %{
$_.Group | Sort LastWriteTime -descending | select -skip 5 | remove-item -WhatIf
}
The key to do what you seek is to use the Group-Object cmdlet.
In your case, the group you want to create is a group containing all items in the same folder. This will give you something like this:
From there, you can perform actions on each group, such as selecting all the files while skipping the first 5 of each folders and deleting the remaining.
See this simple minimalist example:
$Path = 'C:\__TMP\1'
$Items = Get-ChildItem -Path "$path\*.rvt" -Recurse | Group-Object -Property PsparentPath
Foreach ($ItemsGroup in $Items) {
$SortedFiles = $ItemsGroup.Group | sort LastWriteTime -Descending
$SortedFiles | Select-Object -Skip 5 | % {Write-host "Deleting $($_.FullName)"; Remove-Item $_.FullName}
}
Try something like this:
$searchpath = "E:\"
$number = 5
$directories = Get-ChildItem -Path $searchpath -Include *.*.rvt -Recurse | Where-Object {$_.PsIsContainer}
foreach ($dir in $directories)
{
$files = Get-ChildItem -Path $dir.FullName | Where-Object {-not $_.PsIsContainer}
if ($files.Count -gt $number)
{
$files | Sort-Object CreationTime | Select-Object -First ($files.Count - $number) | Remove-Item -Force
}
}
Change the placeholders accordingly. I just gave you the logical approach.
An alternative solution that doesn't require grouping first and instead processes each directory separately:
& { Get-Item $path; Get-ChildItem -Directory -Recurse $path } | # get all dirs.
ForEach-Object { # for each dir.
Get-ChildItem -File $_.FullName/*.*.rvt | # get backup files in dir.
Sort-Object -Descending LastWriteTime | # sort by last-write time, newest first
Select-Object -Skip 5 | # skip the 5 newest
Remove-Item -Force -WhatIf # delete
}
Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.

Powershell Get-Childitem exclude sub directory with in a directory

Hi all I have my folder structure as follows
D:\Exclude
Include
Include1
Exclude
Include
What I need is I would like to filter the directory Include1\Exclude this is what I tried which is not working
$Path ="D:\Exclude"
$DirList = Get-ChildItem -Path "$Path" -Recurse | where {$_.DirectoryName -ne "D:\Exclude\Include1\Exclude"}
$DirList
Use the .FullName property instead of Directory name, like so.
dir $path -Recurse | measure | select Count
Count
-----
4
PS C:\users\Stephen> dir $path -Recurse | ? FullName -ne "R:\Exclude\Include1\Exclude" |
>> measure | select Count
Count
-----
3
use a like with path of your dir to exclude dir and file
Get-ChildItem "D:\Exclude" -Recurse | where FullName -NotLike "D:\Exclude\Include1\Exclude\*"
#short version
gci "D:\Exclude" -Rec | ? FullName -NotLike "D:\Exclude\Include1\Exclude\*"

powershell script statement to fetch a particular file path

I have the following statement in PowerShell script that fetches a particular file
$imptext = "E:\imp\old"
$strAttachment = dir $imptext | sort -prop LastWriteTime | Where-Object {$_.name -like "*Imptextfiles*"} | Where-Object {$_.lastwritetime -gt (Get-Date).AddHours(-1)} | select -last 1 | foreach-object -process { $_.FullName }
How can I write to host the path of that file $strAttachment along with the exact file name?
You want to get the directory of the file? Just use the Split-Path cmdlet:
$attachmentDirectory = Split-Path $strAttachment
You could also use Get-DirectoryName:
$attachmentDirectory =[System.IO.Path]::GetDirectoryName($strAttachment)
Also, you can improve your inital script (using -Filter instead of two Where-Object)
$strAttachment = Get-ChildItem $imptext -Filter '*Imptextfiles*' |
Where-Object Lastwritetime -gt (Get-Date).AddHours(-1) |
sort LastWriteTime |
select -last 1 |
select -ExpandProperty FullName