i tried to make a script which copies all (8 files) files from one folder into a specific subfolder of around ~40 folders...
i start like this with the * to copy all files out of that folder.
But of course it didn't work out like this :
The foldername with the * changes randomly and there is a subfolder called EmailTemplates which should get all my 8 files.
Copy-Item d:\www\example\* -destination d:\example\2\*\EmailTemplates
Is there an easy solution ?
thanks in advance!
Would something like this work for selecting the destination folder?
$destination = Get-ChildItem "D:\example\2" -Recurse | ? {
$_.PSIsContainer -and $_.Name -eq "EmailTemplates"
}
Otherwise you'll probably have to determine the destination like this:
$destination = Get-ChildItem "D:\example\2" |
? { $_.PSIsContainer } |
% { Join-Path $_.FullName "EmailTemplates" } |
? { Test-Path -LiteralPath $_ } | Get-Item
Then copy the files like this:
Get-ChildItem "d:\www\example" | ? { -not $_.PSIsContainer } | % {
Copy-Item $_.FullName $destination.FullName
}
Related
My folder structure looks like this:
AK_Data |--->2020-01-22-------|----->a.txt
| |----->b.txt
| |------>c.tf.err
|
|--->2021-01-15-------|----->d.txt
| |----->b.txt
| |------>x.tf.err
|
|--->2022-01-08-------|----->dv.txt
| |----->pq.bat
|
|--->2022-05-08-------|----->xyz.pdf
AK_Data is the first folder which consists of multiple subfolders like (2020-01-22,2021-01-15.....) and these each subfolders contains 1000 of their different format files.
I need to go into each folder and delete all the files except those files having ".tf.err" in their names. I have used $specificdate='2022-01-01' means the files of the folder less than 2022-01-01 only needs to be deleted. So my expected output is:
AK_Data |--->2020-01-22-------|------>c.tf.err
|
|
|
|--->2021-01-15-------|------>x.tf.err
|
|
|
|--->2022-01-08-------|----->dv.txt (this folder will be untouched since>2022-01-01)
| |----->pq.bat
|
|--->2022-05-08-------|----->xyz.pdf (this folder will be untouched since>2022-01-01)
I only need to delete the files inside the folder, not the folder.
The powershell I used for this is:
cls
$specificdate='2022-01-01'
$destination = 'Y:\Data\Retail\ABC\Development\ak\AK_Data'
$files = Get-ChildItem $destination
$exte='\.(bz2)|(.bat)|(.err)|(~)'
foreach ($f in $files){
$outfile = $f.FullName -notmatch $exte
if ($outfile){
if ($f.Name -lt $specificdate){
$allfiles=Get-ChildItem $f.FullName -Exclude *.tf.err* -Name | remove-item -whatif
}
}
}
It is not deleting the files.
I would do this by first iterating the source folder path for directories with a name that can be converted to a datetime less than the datetime in variabe $specificDate.
Then use Get-ChildItem again inside these folders to find and remove files that do not have .tf.err in their name:
$specificdate = [datetime]::ParseExact('2022-01-01','yyyy-MM-dd', $null)
$sourceFolder = 'Y:\Data\Retail\ABC\Development\ak\AK_Data\*'
Get-ChildItem -Path $sourceFolder -Directory |
Where-Object { [datetime]::ParseExact($_.Name,'yyyy-MM-dd', $null) -lt $specificdate } |
ForEach-Object {
Write-Host "Removing files from folder $($_.Name).."
Get-ChildItem -Path $_.FullName -File |
Where-Object { $_.Name -notlike '*.tf.err*' } |
Remove-Item -WhatIf
}
Again here, I added the -WhatIf switch so you can first see what WOULD happen.
If you're OK with that, remove -WhatIf and run the code again to actually delete the files
I am copying PDF files to the destination folder. I needed to maintain the same folder structure as the source folder.
I managed to copy and maintain the folder structure but somehow it is not selecting based on my where creationtime criteria.
$archive_MonthlyStatement = "D:\Archives\Monthly_Statement"
$path2 = "D:\Temp\Test_Output\"
$scan_monthStatement = Get-ChildItem $archive_MonthlyStatement | Where-Object {
(( $_.PSIsContainer ))
} | Where {
$_.CreationTime -lt (Get-Date).AddDays(-730)
} | Copy-Item -Destination "$path2" -Recurse -Container
Expected outcome:
Source folder:
Archives\Reports\Branch1\2015\pdf files
Archives\Reports\Branch1\2016\pdf files
Archives\Reports\Branch1\2017\pdf files
Archives\Reports\Branch1\2018\pdf files
Archives\Reports\Branch1\2019\pdf files
Destination folder:
Archives\Reports\Branch1\2015\pdf files
Archives\Reports\Branch1\2016\pdf files
Archives\Reports\Branch1\2017\pdf files
Actual outcome:
Destination folder:
Archives\Reports\Branch1\2015\pdf files
Archives\Reports\Branch1\2016\pdf files
Archives\Reports\Branch1\2017\pdf files
Archives\Reports\Branch1\2018\pdf files
Archives\Reports\Branch1\2019\pdf files
Somehow it is copying all as long as the parent directory creation time is more than 730 days.
check the creationtime of each file and copy it.
$srcDir = "D:\Archives\Monthly_Statement"
$destDir = "D:\Temp\Test_Output"
Get-ChildItem $srcDir -Filter *.pdf -Recurse |
Where-Object CreationTime -lt (Get-Date).AddDays(-730) |
ForEach-Object {
$destFile = [IO.FileInfo]::new($_.FullName.Replace($srcDir, $destDir))
if($destFile.Exists) { return }
if(!$destFile.Directory.Exists) { $destFile.Directory.Create() }
$_.CopyTo($destFile)
}
I have subfolders, and subsubfolders. In the subsubfolders, I want to find all subfolders without a file named PKA.dump. Can this be done in powershell?
The subfolders go from Angle1, Angle2, etc up to Angle24
The subsubfolders go from 1eV, 2eV, to 150eV.
I can find when they are less than a certain size:
Get-Childitem -path . -filter "PKA.dump" -recurse | where {$_.Length -le 500}
But what if they dont exist?
If you have just 2 levels of directories, don't recurse. Do something like this instead:
Get-ChildItem -Path . -Directory | Get-ChildItem -Directory | ? {
-not (Test-Path -LiteralPath (Join-Path $_.FullName 'PKA.dump'))
}
For a deeper folder structure this should be ok:
Get-ChildItem -Path C:\yourpath\ -recurse | where {$_.psiscontainer} | % {
if((Get-ChildItem -Path $_.FullName -File).name -notcontains "pka.dump"){ $_.FullName }
}
I Need some help here: the following script needs to be changed so, that the script delete only Folders in the Subdirectory not Files. Can anyone help me?
$path = "C:\test\1"
$keep = 3
$strLogFileName = "c:\test\yourlogfile.log";
function Log-Message
{
Param ([string]$logtext)
Add-content $strLogFileName -value $logtext
}
$dirs = Get-ChildItem -Path $path -Recurse | Where-Object {$_.PsIsContainer}
foreach ($dir in $dirs) {
$files = Get-ChildItem -Path $dir.FullName | Where-Object {-not $_.PsIsContainer -and $_.name - like "*.zip"}
if ($files.Count -gt $keep) {
$files | Sort-Object CreationTime -desc| Select-Object -First ($files.Count - $keep) |
% { $dt=get-date;(Log-Message "Deleting File $_ on $dt");$_ }| Remove-Item -Force
}
}
My original answer was -WAY- off base, and having RTFQ I've got something that should work for you.
function Remove-LargeFolders
{
Param([string]$RootPath)
$keep = 5
#Get a list of the dirs in the first level of the folder
$dirs = Get-ChildItem -Path $RootPath | Where-Object {$_.PsIsContainer}
foreach ($dir in $dirs) {
#Call function on the new folder to check all the sublevels before deleting
#the top-level folder.
Remove-LargeFolders $dir.FullName
$files = Get-ChildItem -Path $dir.FullName | Where-Object {-not $_.PsIsContainer `
-and $_.name -like "*.zip"}
if ($files.Count -gt $keep) {
$dt=get-date
Log-Message "Deleting Folder $dir on $dt"
$dir
Remove-Item $dir.FullName -Force -Recurse
}
}
}
This should do what you're looking for. The answer was recursion! Essentially, the script only looks at one level of folders at a time. It digs down to the bottom of each folder tree, before working it's way back up to the top.
This script will work as written, but there is a proviso. Right now, if the script is targeting a structure like this:
Target Folder (4 files)
SubFolder (10 files)
SubSubFolder (5 files)
It will check SubSubFolder first and not delete it, since it has 5 or fewer files. However, once it hops back up to SubFolder, it will see a folder that is too big and kill it off, getting rid of SubSubFolder in the process. If you want a way around that, you'll need to build in some checks that will allow you to see if each folder has another folder in it before deleting.
Hope this helps more!
I want to delete all the content and the children of a given root folder, however i want to keep some files (the logs), which all reside in a logs folder
What is the elegant way of doing this in powershell.
Currently i am doing it in multile steps, surely this can be done easily... i have a feeling my oo-ness/language bias is getting in the way
eg
c:\temp
c:\temp\logs
c:\temp\logs\mylog.txt
c:\temp\logs\myotherlog.log
c:\temp\filea.txt
c:\temp\fileb.txt
c:\temp\folderA...
c:\temp\folderB...
after delete should just be
c:\temp
c:\temp\logs
c:\temp\logs\mylog.txt
c:\temp\logs\myotherlog.log
this should be simple; i think 12:47am-itis is getting me...
Thanks in advance
RhysC
dir c:\temp | where {$_.name -ne 'logs'}| Remove-Item -Recurse -force
Here is a general solution:
function CleanDir($dir, $skipDir) {
write-host start $dir
Get-ChildItem $dir |
? { $_.PsIsContainer -and $_.FullName -ne $skipDir } |
% { CleanDir $_.FullName $skipDir } |
? { $skipDir.IndexOf($_, [System.StringComparison]::OrdinalIgnoreCase) -lt 0 } |
% { Remove-Item -Path $_ }
Get-ChildItem $dir |
? { !$_.PsIsContainer } |
Remove-Item
$dir
}
CleanDir -dir c:\temp\delete -skip C:\temp\delete\logs
It works recursivelly. The first parameter to CleanDir is the start directory. The second one ($skipDir) is the directory that should not be deleted (and its content shouldn't be as well).
Edited: corrected confusing example ;)