We deal with over a thousand files. I want to use Powershell to automate removing files older than a year for each folder path after checking to see if it exists in the archive location. It it does, it removes from backup. It if does not, it moves the file from backup to archive locations. I am not sure what is wrong with my code. It does not give me an error message that I can go off on. When I find the value for each variable, everything looks fine to me. What is happening is that the files are not being moved over.
Function Delete-Files ($src)
{
#finding date to remove i.e, if today's date is 5/19/2021, then the code would only be looking at files that are before 5/19/2020 12:00:00 AM
$date2remove = (Get-Date).Date.AddYears(-1)
$clientLocation = "\\fileshare\test\test\test\Backup\Client\"
#getting Client folder #
$clients = (Get-ChildItem $clientLocation -Directory).name
foreach ($client in $clients)
{
$srcparent = $clientLocation + $client + $src -join "\"
#ignoring the paths that do not contain $src
if (Test-Path $srcparent)
{
#getting files that are older than a year
$files2remove = Get-ChildItem $srcparent | Where-Object {( $_.LastWriteTime -lt $date2remove)}
foreach ($file2remove in $files2remove)
{
#getting the year for the last write time for each file
$year2remove = $file2remove.LastWriteTime.Year
$archive = '\\fileshare\test\test\test\archive\' + $year2remove + '\Client\' + $client + $src -join '\'
#if archive folder doesn't exist, create
if (!(Test-Path $archive))
{
New-Item -Path $archive
}
#getting the name of each file that needs to be removed
$fileName2remove = $file2remove.name
$archiveFile = $archive + $fileName2remove -join '\'
$srcFile = $srcparent + $fileName2remove -join '\'
#if file exists in archive, remove
if (Test-Path $archiveFile)
{
Remove-Item -Path $srcFile
"$srcFile"
}
#if file does not exist, move file from backup to archive
else
{
Move-Item -Path $srcFile -Destination $archive
"$archiveFile"
}
}
}
}
}
$src = "\folder1\"
Delete-Files $src
$src = "\folder1\folder2\"
Delete-Files $src
$src = "\folder3\"
Delete-Files $src
Related
The code below has been wonderful so far for organising my hard-drives.
I do face this error when I transfer large amounts of data:
Move-Item : Cannot create a file when that file already exists.
This happens when I move a file that is duplicate, is there a way to rename the duplicate file in some sort of sequence?
That would be much appreciated :))
# Get all files
Get-ChildItem "C:\zAa" -File -Recurse | ForEach-Object {
# Get the modified date
$dt = Get-Date $_.LastWriteTime
$year = $dt.Year
$month = $dt.Month
# This adds "0" in front of the 1-9 months
if($dt.Month -lt 10) {
$month = "0" + $dt.Month.ToString()
} else {
$month = $dt.Month
}
# Remove leading '.' from the extension
$extension = $_.Extension.Replace(".", "")
# Where we want to move the file
$destinationFolder = "C:\zBb\$extension\$year\$month\"
# Ensure full folder path exists
if(!(Test-Path $destinationFolder)) {
New-Item -ItemType Directory -Force -Path $destinationFolder
}
# Copy/Move the item to it's new home
Move-Item $_.FullName $destinationFolder
}
I haven't been able to do much, I normally go find the duplicates and rename them manually.
Probably the easiest way to move a file with a unique name is to use a Hashtable that stores the filenames already present.
Then a simple loop can add a sequence number to its file name until it is no longer found in the Hashtable.
Next simply move the file under that new name.
Your code modified:
# Where we want to move the file
$destinationFolder = 'C:\zBb\{0}\{1:yyyy}\{1:MM}' -f $_.Extension.TrimStart("."), $_.LastWriteTime
# Ensure full folder path exists
$null = New-Item -Path $destinationFolder -ItemType Directory -Force
# create a Hashtable and store the filenames already present in the destination folder
$existing = #{}
Get-ChildItem -Path $destinationFolder -File | ForEach-Object { $existing[$_.Name] = $true }
# Get all source files
Get-ChildItem "C:\zAa" -File -Recurse | ForEach-Object {
# Copy/Move the item to it's new home
# construct the new filename by appending an index number in between brackets
$newName = $_.Name
$count = 1
while ($existing.ContainsKey($newName)) {
$newName = "{0}({1}){2}" -f $_.BaseName, $count++, $_.Extension
}
# add this new name to the Hashtable so it exists in the next run
$existing[$newName] = $true
# use Join-Path to create a FullName for the file
$newFile = Join-Path -Path $destinationFolder -ChildPath $newName
Write-Verbose "Moving '$($_.FullName)' as '$newFile'"
$_ | Move-Item -Destination $newFile -Force
}
I am trying to create myself a powershell script that has mainly two tasks - one after the other.
Initial assumptions: it runs where it performs the following tasks.
Trace all the files, those that are folders - make a zip of them, then after making the archive, delete them. Objective accomplished.
Write to the file the names of all files in the folder (after completing point 1) but check if the given file has the extension of *.zip
a) if it has extension of *.zip then it should be saved in .txt file like "uresoruce = foo/file.zip"
b) if it doesn't have extension *.zip then it should be saved to a .txt file like this "resoruce = foo/file2.jar"
c) since the script is started from the place where all the files are, it will probably also be saved to a file, I would like to avoid this
Suppose we have some files in a folder after compiling, and we don't have any folder inside. The .txt file should look like the following:
uresource = plugins/Liula_1.0.0.0.zip
uresource = plugins/Liborts_3.7.1.0.zip
uresource = plugins/Liwer_1.2.0.0.zip
resource = plugins/o0.I20100512-1500.jar
resource = plugins/or.v20100505-1235.jar
The script I managed to write so far:
## set current path
$path = (Resolve-Path .\).Path
## dirs in a path
$source = Get-ChildItem -Path $path -Filter "" -Directory
$files = Get-ChildItem $path
Add-Type -assembly "system.io.compression.filesystem"
Foreach ($s in $source) {
$destination = Join-path -path $path -ChildPath "$($s.name).zip"
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $destination)
Remove-Item $s -Recurse
}
# This does not working!!! :/
Foreach ($f in $files) {
$extn = [IO.Path]::GetExtension($f)
if ($extn -eq ".zip" ) {
$outfile = "uresource = plugins/" + $f.Name
}
else {
$outfile = "resource = plugins/" + $f.Name
}
}
As #Santiago Squarzon rightly pointed out I did not do anything with this variable. I got a little confused because before I did it only for out-file I didn't use -append and in fact I got the last value in .txt. Now I made my first script in ph, it works like a dream ;)
## set current path
$path = (Resolve-Path .\).Path
## dirs in a path
$source = Get-ChildItem -Path $path -Filter "" -Directory
$files = Get-ChildItem $path
Add-Type -assembly "system.io.compression.filesystem"
## create zip and delete other dirs
Foreach ($s in $source) {
$destination = Join-path -path $path -ChildPath "$($s.name).zip"
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $destination)
Remove-Item $s -Recurse
}
## output filename in .txt
$logFile = "$pwd\logfile.txt"
Foreach ($f in $files) {
$extn = [IO.Path]::GetExtension($f)
if ($extn -eq ".zip" ) {$outfile = "uresource = plugins/$f"}
else {$outfile = "resource = plugins/$f"}
$outfile | Out-File -Append $logFile
}
Currently, I am writing a script that moves PDF files that are wrongfully zipped to a certain folder. These files will then get unzipped and the contained files will get moved to a different folder. This all works at the moment.
What i need to add now is the following: I want to make it so that it automatically renames the contained file to the name the original ZIP file had.
So when i have a ZIP file called "testzip" and the contained file is called "testcontained", i want it to rename "testcontained" to "testzip".
This would be useful in keeping track of which files are associated with which ZIP-files.
Param (
$SourcePath = 'Z:\Documents\16_Med._App\Auftraege\PDFPrzemek\struktur_id_1225\',
$ZipFilesPath = 'Z:\Documents\16_Med._App\Auftraege\PDFPrzemek\Zip',
$UnzippedFilesPath = 'Z:\Documents\16_Med._App\Auftraege\PDFPrzemek\Zip\unzipped'
)
$VerbosePreference = 'Continue'
#region Test folders
#($SourcePath, $ZipFilesPath, $UnzippedFilesPath) | Where-Object {
-not (Test-Path -LiteralPath $_)
} | ForEach-Object {
throw "Path '$_' not found. Make sure that the folders exist before running the script."
}
#endregion
#region Get all files with extension .pdf
$Params = #{
Path = Join-Path -Path $SourcePath -ChildPath 'ext_dok'
Filter = '*.pdf'
}
$PDFfiles = Get-ChildItem #Params
Write-Verbose "Got $($PDFfiles.count) files with extension '.pdf' from '$($Params.Path)'"
#endregion
#region Move PDF and HL7 files
$MDMpath = Join-Path -Path $SourcePath -ChildPath 'MDM'
foreach ($PDFfile in ($PDFfiles | Where-Object {
(Get-Content $_.FullName | Select-Object -First 1) -like 'PK*'})
) {
$MoveParams = #{
Path = $PDFfile.FullName
Destination = Join-Path -Path $ZipFilesPath -ChildPath ($PDFfile.BaseName + '.zip')
}
Move-Item #MoveParams
Write-Verbose "Moved file '$($MoveParams.Path)' to '$($MoveParams.Destination)'"
$GetParams = #{
Path = Join-Path -Path $MDMpath -ChildPath ($PDFfile.BaseName + '.hl7')
ErrorAction = 'Ignore'
}
if ($HL7file = Get-Item #GetParams) {
$MoveParams = #{
Path = $HL7file
Destination = $ZipFilesPath
}
Move-Item #MoveParams
Write-Verbose "Moved file '$($MoveParams.Path)' to '$($MoveParams.Destination)$($HL7file.Name)'"
}
}
#endregion
#region Unzip files
$ZipFiles = Get-ChildItem -Path $ZipFilesPath -Filter '*.zip' -File
foreach ($ZipFile in $ZipFiles) {
$ZipFile | Expand-Archive -DestinationPath $UnzippedFilesPath -Force
Write-Verbose "Unzipped file '$($ZipFile.Name)' in folder '$UnzippedFilesPath'"
}
#endregion
As you might have noticed, i am unzipping PDF files, which is kinda weird. Let me explain:
We have a lot PDF's that cant be opened. After running some checks, we came to the conclusion that some of them are wrongfully Zipped. To find which ones, i check the first bytes of the PDF files. If they contain "PK*", they are ZIP-Files.
To unzip them with the script, i need to rename them to change the file extension to ".zip".
If the files have ".pdf", then you cant unzip them, even if they are technically zipped.
So, does anyone have an idea on what i could do so that it gets automatically renamed?
Thanks in advance! if theres any missing info, let me know.
UPDATE
I have now tested something, but it isnt working.
This is my attempt at making this work:
ForEach ($File in (Get-ChildItem $UnzippedFilesPath))
{ #rename unzipped file
Rename-Item $File.Name -NewName ($ZipFile.BaseName)
}
The issue is that i dont know how to call back to the original zip file. I dont think using $ZipFile works.
This is the error i get:
Rename-Item : Cannot rename because item at 'test.txt' does not exist.
At line:4 char:2
+ Rename-Item $File.Name -NewName ($ZipFile.BaseName)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Rename-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.RenameItemCommand
So lets say I want to copy the file test.txt to another folder, but I want it to put create a copy and not just erase the file.
I know that Copy-Item overwrites the file in the destination folder but I don't want it to do that.
It also has to be a function
I think this will help you:
$destinationFolder = 'PATH OF THE DESTINATION FOLDER'
$sourceFile = 'FULL PATH AND FILENAME OF THE SOURCE FILE'
# split the filename into a basename and an extension variable
$baseName = [System.IO.Path]::GetFileNameWithoutExtension($sourceFile)
$extension = [System.IO.Path]::GetExtension($sourceFile)
# you could also do it like this:
# $fileInfo = Get-Item -Path $sourceFile
# $baseName = $fileInfo.BaseName
# $extension = $fileInfo.Extension
# get an array of all filenames (name only) of the files with a similar name already present in the destination folder
$allFiles = #(Get-ChildItem $destinationFolder -File -Filter "$baseName*$extension" | Select-Object -ExpandProperty Name)
# construct the new filename
$newName = $baseName + $extension
$count = 1
while ($allFiles -contains $newName) {
# add a sequence number in brackets to the end of the basename until it is unique in the destination folder
$newName = "{0}({1}){2}" -f $baseName, $count++, $extension
}
# construct the new full path and filename for the destination of your Copy-Item command
$targetFile = Join-Path -Path $destinationFolder -ChildPath $newName
Copy-Item -Path $sourceFile -Destination $targetFile
Even if i isn't the most elegant way, you could try something like this
$src = "$PSScriptRoot"
$file = "test.txt"
$dest = "$PSScriptRoot\dest"
$MAX_TRIES = 5
$copied = $false
for ($i = 1; $i -le $MAX_TRIES; $i++) {
if (!$copied) {
$safename = $file -replace "`.txt", "($i).txt"
if (!(Test-Path "$dest\$file")) {
Copy-Item "$src\$file" "$dest\$file"
$copied = $true
} elseif (!(Test-Path "$dest\$safename")) {
Copy-Item "$src\$file" "$dest\$safename"
$copied = $true
} else {
Write-Host "Found existing file -> checking for $safename"
}
} else {
break
}
}
The for-loop will try to safely copy the file up to 5 times (determined by $MAX_TRIES)
If 5 times isn't enough, nothing will happen
The regEx will create test(1).txt, test(2).txt, ... to check for a "safe" filename to copy
The if-statement will check if the original file can be copied
The elseif-statement will try to copy with the above created $safename
The else-statement is just printing a "hint" on what's going on
hi i am trying to unzip folders and sub folders i have tried different ways and script but no luck.
Can some one help on this
$Date = Get-Date
#
$folder_date = $Date.ToString("yyyy-MM-dd_HHmmss")
$content = get-childitem 'C:\Deployments'
$sortedContent = $content | Sort-Object LastWriteTime -Descending
# 1. LIST BACKUPS
write-host "This is the list of all the Deployments :"
$count = 1
foreach ($item in $sortedContent)
{
#Edit: Now with auto-incrementing counter
Write-Host ("{0}: {1}" -f $count, $item.Name)
$count++
}
$itemNumber = Read-Host "Please select which deployments you want to copy "
$itemNumber = $itemNumber -1
if($sortedContent[$itemNumber].PSIsContainer -eq $true)
{
$src = $sortedContent[$itemNumber].FullName + "\"
$Date = Get-Date
$folder_date = $Date.ToString("yyyy-MM-dd_HHmm")
$tempPath = 'C:\_Temp\Restore' + $folder_date
if (!(Test-Path -path $tempPath))
{
New-Item $tempPath -type directory
}
$TabletzipPath = $src + "table.zip"
$AdminzipPath = $src + "admin.zip"
.\unzip.ps1 $src $tempPath
.\unzip.ps1 $TabletzipPath $tempPath
.\unzip.ps1 $AdminzipPath $tempPath
}
$Shell = new-object -com shell.application
$Zip = $Shell.NameSpace($PathToZip)
ForEach($Item in $Zip.items())
{
$Shell.Namespace($ExtractPath).copyhere($Item)
}
If your just looking for an easy & quick way of doing this.
You can use this function:
Unzip-File -File C:\location.zip -Destination E:\destination
Need this script:
http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Function-to-727d6200
Using jar unzipping: copy-paste it into PowerShell ISE or create a .ps1 file with this code:
#choose directory where your script is
cd $PSScriptRoot
#do for each file in your directory, -recurse stands for all subfolders, *.jar stands for all files with jar extension
foreach ($file in (dir -Recurse *.jar))
{
#Uncomment this to check files this script is going to unzip (don't forget to comment 7z line below to avoid operation)
#Write-Host ("Dir for file " + $file.Name + " is " + $file.Directory)
#put here full path to 7z if there is no system env (or just make it) for that
#x stands for eXtract files with full paths
#-o is for output folder (example of usage -oc:\test\)
7z x $file.FullName ("-o"+$file.Directory)
}
It should unzip everything you need directly to the folder where your .jar (or any other archive) is.