Powershell Get-Childitem exclude sub directory with in a directory - powershell

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\*"

Related

How to delete all but the most recent files in a directory of folders and files

I have a folder that has a bunch of backups in in separated by folder. I want a script to use the directory (C:\Users\user\Desktop\TEST) and in that directory I have any number of folders with any number of files in them, I only want to keep the latest in the folder for every folder in the directory and delete the rest.
I have this but it only does 1 folder at a time and it has to be hardcoded.
$path = "C:\Users\user\Desktop\TEST\Folder1"
$FileNumber = (get-childitem $path).count - 1
get-childitem -path $path | sort CreationTime -Descending | select -last $FileNumber | Remove-Item -Force -WhatIf
Is there any way to automate this?
Thanks,
You can try this:
$Path = "C:\Users\user\Desktop\TEST"
$Folders = Get-ChildItem $Path
foreach ($Folder in $Folders)
{
$FolderName = $Folder.FullName
$Files = Get-ChildItem -Path $FolderName
$FileNumber = $Files.Count - 1
$Files | sort CreationTime -Descending | select -last $FileNumber | Remove-Item -Force -WhatIf
}
You would need a loop of your choice to accomplish this, this example uses ForEach-Object. Instead of using Select-Object -Last N you could just use Select-Object -Skip 1 to skip the newest file. Also note the use of -Directory and -File with Get-ChildItem to filter only directories or only files.
$path = "C:\Users\user\Desktop\TEST\Folder1"
# Get all Directories in `$path`
Get-ChildItem $path -Directory | ForEach-Object {
# For each Directory, get the Files
Get-ChildItem $_.FullName -File |
# Sort them from Newest to Oldest
Sort-Object CreationTime -Descending |
# Skip the first 1 (the newest)
Select-Object -Skip 1 |
# Remove the rest
Remove-Item -Force -WhatIf
}

powershell count number of defined files in defined subfolder

I have N different directories (titles are random and do not have test pattern in string)
C:\Folder\test1\file.txt
C:\Folder\test2\file.txt
...
C:\Folder\testN\file.txt
I want to count number of file.txt files in Folder dir in all test1..testN subdirectories using powershell, in example C:\Folder\*\file.txt
I started with below code, but it counts all files
Write-Host ( Get-ChildItem C:\Folder | Measure-Object ).Count;
Could you pls help?
Updated: I dont need file.txt files in test1...N subfolders, only in test1...N folder In example - C:\Folder\*\file.txt, but not C:\Folder\*\abc\file.txt
If I understand the question properly, you would like to get the count of all *.txt files inside a rootfolder, 1 level deep, where the direct parent foldername is called testX (X is a sequence number).
You have a structure like this:
C:\FOLDER
+---test1
| | file1.txt
| |
| \---abc
| file1.txt
|
+---test2
| file1.txt
|
\---test3
file1.txt
For that you can use
(Get-ChildItem -Path 'C:\Folder' -Filter '*.txt' -Depth 1 |
Where-Object { $_.Directory.Name -match '^test\d+$' }).Count
which in the example structure above returns 3
Edited: I think I got what you want now.
Clear-Host
$TestPath = "C:\Folder"
$FileCnt = 0
$Dirs = Get-ChildItem -Path "$TestPath" -Directory
ForEach ($Dir in $Dirs) {
$FileCnt += (Get-ChildItem -Path "$($($Dir).FullName)\*.*" -Filter "file.txt" |
Measure-Object).count
}
$FileCnt
PMental's solution below is more elegant but this also works.
HTH
This should do it:
(Get-ChildItem C:\Folder -Filter file.txt -File -Recurse -Depth 1 | Measure-Object).Count
or if you only want text files from the subfolders and not from C:\Folder itself, this one:
$Path = 'C:\Folder'
$Files = Get-ChildItem $Path -Filter file.txt -File -Recurse -Depth 1 |
Where-Object PSParentPath -notlike "*::$Path"
($Files | Measure-Object).Count
Edited: Edited to only count "file.txt" files.
You're close, this should get you the total count of file.txt files any folder C:\Folder\Test*
Write-Host ( Get-ChildItem C:\folder\test* -Directory | Get-ChildItem -Include file.txt | Measure-Object ).Count

Delete X files in each folders and sub folders

I want to delete files in a folder and its subfolders but not X last files again in each folder. For example in C:\Test I want to keep 10 txt files but also in C:\Test\subtest1 and C:\Test\subtest2. Here, X X is the number of files I want to keep.
But it will not keep 10 files in each folder but in the entire arborescence.
My script is not fully functional, but it did it well in the C:\Test directory:
Set-ExecutionPolicy unrestricted $txtfiles = 'C:\Users\MUC8VX\Documents\Test
ForEach-Object { Get-ChildItem $txtfiles | where{ -not $_.PsIsContainer}|
sort LastWriteTime -desc| select -Skip 10 |
Remove-Item -Include *.txt* -Force }
And if I add -Recurse it will not keep 10 files in each folders but in the entire arborescence:
Set-ExecutionPolicy unrestricted
$txtfiles =`C:\Users\MUC8VX\Documents\Test'
ForEach-Object { Get-ChildItem $txtfiles -Recurse | where{ -not
$_.PsIsContainer}| sort LastWriteTime -desc|
select -Skip 10 | Remove-Item -Include *.txt* -Force }
edit :
Thanks a lot Manuel Batsching.
Here's a generic script :
#Insert your parent folder which contains files and subfolders
Get-Childitem -Path C:\Your\Parent\Folder -Recurse |
Group-Object Directory |
ForEach-Object {
$_.Group |
#sort by the last written files
Sort-Object LastWriteTime -Descending |
#Keep the X last files you want to keep
Select-Object -Skip X |
#Remove files according to their extension
Remove-Item -Include *.extension* -Force }
I haven't tested but you can try this.
Set-ExecutionPolicy unrestricted
$txtfiles = 'C:\Users\MUC8VX\Documents\Test'
Get-ChildItem -Directory -Recurse -Path $txtfiles | ForEach-Object {
Get-ChildItem -Path $_.fullname -Include *.txt | Sort-Object LastWriteTime -Descending | Select-Object -Skip 10 | Remove-Item -Force
}
Basically, this code iterate over each folder recursively, for each folder, it find the files, skip 10 and remove all others.
If you are looking for a solution, that also applies to nested subfolders, you can list all files recursively and then group them by the path of their respective parent folder. Then apply your sorting rules and reduce each group to 10 elements.
Get-Childitem *.txt -Recurse |
Group-Object Directory |
ForEach-Object {
$_.Group |
Sort-Object LastWriteTime -Descending |
Select-Object -Skip 10 |
Remove-Item }

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

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

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