Why is a string containing comma separated paths built using join not accepted as a path when attempting Compress-Archive in Powershell - powershell

Compress-Archive states that the Path parameter accepts a comma separated list of directories.
-Path
Specifies the path or paths to the files that you want to add to the archive zipped file. To specify multiple paths, and include files in multiple locations, use commas to separate the paths.
The following code builds a comma separated list of paths, but results in an error stating the path is not valid.
Code
$now = Get-Date
Write-Host "Zipping logs... $now"
$dirZip = #()
foreach ($vm in $vms)
{
$vmName = $vm.name
$dirZip += "C:\Scripts\ClientLogs\$vmName"
}
$currentDate = Get-Date -Format "MM-dd-yyyy"
$zipDestinationPath = "C:\Scripts\" + $currentDate + "_Client_Logs.zip"
Compress-Archive -Path ($dirZip -join ',') -DestinationPath $zipDestinationPath -Force
Error
Compress-Archive : The path 'C:\Scripts\ClientLogs\Client1,C:\Scripts\ClientLogs\Client2,C:\Scripts\ClientLogs\Client3,C:\Scripts\ClientLogs\Client4,C:\Scripts\ClientLogs\Client5' either
does not exist or is not a valid file system path.
At C:\Scripts\VM Copy Files.ps1:169 char:5
+ ... Compress-Archive -Path ($dirZip -join ',') -DestinationPa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (C:\Scripts\Clie...entLogs\Client5:String) [Compress-Archive], InvalidOperationException
+ FullyQualifiedErrorId : ArchiveCmdletPathNotFound,Compress-Archive
Copying the "invalid path" from the error message and using it directly in a Compress-Archive works though...
Compress-Archive -Path C:\Scripts\ClientLogs\Client1,C:\Scripts\ClientLogs\Client2,C:\Scripts\ClientLogs\Client3,C:\Scripts\ClientLogs\Client4,C:\Scripts\ClientLogs\Client5 -DestinationPath C:\temp\test.zip
I've tried building the Path value by just concatenating strings and passing it as a variable, but that resulted in the same error.
$now = Get-Date
Write-Host "Zipping logs... $now"
foreach ($vm in $vms)
{
$vmName = $vm.name
$dirZip = $dirZip + "C:\Scripts\ClientLogs\$vmName,"
}
$currentDate = Get-Date -Format "MM-dd-yyyy"
$zipDestinationPath = "C:\Scripts\" + $currentDate + "_Client_Logs.zip"
$dirZip = $dirZip.trimend(",")
Compress-Archive -Path $dirZip -DestinationPath $zipDestinationPath -Force

Related

using PowerShell to rename all files in a folder to each files last write time

$getdate = Get-Date -Format "yyyymmddHHmmss"
Get-ChildItem -Path C:\blah\*.tiff | foreach { rename-item -Path $_.FullName -NewName "($getdate).tif" }
This just tells me that the file already exists as if its trying to change them all to the same date and time.
This is what each file should be renamed as though but ending in .tif and not .tiff.
Get-ChildItem -Path C:\blah\* | Get-Date -Format "yyyymmddHHmmss"
20221413111408
20222013112039
20225413115422
20221816071813
How do I get this to work so that each file that comes into his folder is renamed when I run this.
I have also tried this:
Get-ChildItem -Path C:\Blah\*.tiff | foreach { rename-item -Path $_.FullName -NewName "Get-Date -Format ("yyyymmddHHmmss").tif" }
Which gives me this error:
Rename-Item : A positional parameter cannot be found that accepts argument 'yyyymmddHHmmss).tif'.
At line:1 char:52
+ ... | foreach { rename-item -Path $_.FullName -NewName "Get-Date -Format ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.RenameItemCommand
It's currently trying to rename all files to the same date timestamp because you're asking it to - the value stored in $getdate is not going to automatically update itself :)
Instead, you'll want to call Get-Date every time you rename an individual file by passing a scriptblock to the -NewName parameter - PowerShell will then re-evaluate the scriptblock for every file it's renaming:
Get-ChildItem -Path C:\blah*.tiff |Rename-Item -NewName { "$($_ |Get-Date -Format 'yyyymmddHHmmss').tif" }
As Santiago points out, this will still fail with a naming collision if you have multiple image files that were last written/modified within the same wallclock second.

Powershell, set path as an everyday autocreated folder

I have a folder that is created every morning and named as 'ddMMyy' (I know EU date formats are not powershell's best friend ...)
I'm trying to set a path in a script as the folder with the current date :
$date = Get-Date -Format ddMMyy
$root = "X:\test\$date"
$files = Get-ChildItem -Path $root -filter *.*
But the script keeps looking for files in the "test" folder and not the folder '190422'
What am I doing wrong ?
Here is the rest of the code :
$date = Get-Date -Format ddMMyy
$root = "X:\test\$date"
$files = Get-ChildItem -Path $root -filter *.*
#Starting on Row 2
[int]$i = 2
ForEach ($file in $files){
#Client
$cs = switch -Regex -File $file {
# exit the switch if we reach a line with 'Command: MANUAL ROLLOVER'
'Command: MANUAL ROLLOVER' { break }
# parse the string into named matches
'^(?<date>\d{2}/\d{2}/\d{4})\s+(?<time>\d{2}:\d{2}:\d{2})\s+(?<idleft>[^\s]+)\s+(?<idright>\d+)\s+(?<error>\d+)\s+(?<details>(.+))$' {
# output an object with the wanted properties
$st = '{0}-{1}' -f $matches['idleft'], $matches['idright']
}
}
$row = $i
$Column = 1
$workbook.Cells.Item($row,$column) = "$st"
and the error PS gives me :
Cannot find path 'X:\test\FILE.001' because it does not exist.
At X:\test\script.ps1:38 char:27
+ $cs = switch -Regex -File $file {
+ ~~~~~
+ CategoryInfo : ObjectNotFound: (X:\test\FILE.001:String) [], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound"
Rather than cast the $root, why not do a Join-Path instead?
Join-Path -Path X:\test -ChildPath $date
This will ensure the slashes are aligned as well.
Also, I would suggest using a name other than $root - something like $SearchDir. This is because Root can have other meanings.

PowerShell copy-item

I am trying to copy latest 30days files to the folder by this code:
$month = (get-date).AddDays(-30).ToString("yyyMM")
$lastmonthfiles = Write-Host (-join('DCP_', $month,"*.csv"))
Copy-Item -Path Write-Host (-join ("C:\DC+\History\", $lastmonthfiles)) -Destination C:\DC+\History\Backup
but I am having a problem in path in copy-item instruction, which is
Copy-Item : A positional parameter cannot be found that accepts argument 'C:\DC+\History\'.
At line:5 char:1
+ Copy-Item -Path Write-Host (-join ("C:\DC+\History\", $lastmonthfiles ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Copy-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
I am new in PowerShell, and programming so, I could not understand, how can I update and achieve a goal.
Try this:
$Source = Get-Item "C:\Games"
$Destination = "E:\Backup"
$LogFile = "C:\Copy-LogFile.txt"
Copy-Item -Path $( $Source | Where LastWriteTime -LE (Get-Date).AddDays(-30) ) -Destination $Destination -Recurse -PassThru |
Out-File $LogFile -Force
This takes care of your copy function and generates an output log.
Sorry, but your code makes no sense to me...
If it is your aim to copy files to a subfolder in a backup path, try this:
# get the date to use as subfolder to copy to and also to filter the last 30 days files
$refDate = (Get-Date).AddDays(-30).Date # .Date sets it to midnight
# set this variable to the folder where the csv are to be found
$sourceFolder = 'X:\Path\To\Where\The\Files\Are'
# create a destination path to copy to (just a string)
$destination = Join-Path -Path 'C:\DC+\History\Backup' -ChildPath ($refDate.ToString("yyyMM"))
# create this destination folder
$null = New-Item -Path $destination -ItemType Directory -Force
# get the files and copy them to the destination folder
Get-ChildItem -Path $sourceFolder -Filter '*.csv' -File | # filter on CSV fies only
Where-Object { $_.LastWriteTime -ge $refDate } | # filter on date 'last 30 days'
Copy-Item -Destination $destination -Force

Positional parameter cannot be found error in powershell

I am trying to append the date to a file name in my Powershell script but keep getting the following error (my code is below the error). Any help/direction would be greatly appreciated. Thank you.
Set-Content : A positional parameter cannot be found that accepts
argument '$null'.
At P:\CoverageVerifier\CombineTextFiles.ps1:8 char:50
+ ... thTrailer | Set-Content "${path}\\" + ${$dateStr} + "_CoverageVerifi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-Content], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.SetContentCommand
Here is my powershell code:
$path = "\\xx\\apps\\CoverageVerifier\\"
$pathHeader = "\\xx\\apps\\CoverageVerifier\\Header.txt"
$pathData = "\\xx\\apps\\CoverageVerifier\\Data.txt"
$pathTrailer = "\\xx\\apps\\CoverageVerifier\\Trailer.txt"
$date = Get-Date
$dateStr = $date.ToString("yyyyMMdd")
#Write-Output $dateStr
Get-Content $pathHeader,$pathData,$pathTrailer | Set-Content "${path}\\cvgver." + ${dateStr} + ".0101"
The first positional parameter of the Set-Content cmdlet is the -Path parameter.
Because of the way you define the paths for the files, it is bound to have problems with that.
As I understand, these are UNC paths, so try this instead:
# for LOCAL paths
# Set the driveletter to the actual drive you are using. For demo I'm using 'X:\'
# $path = 'X:\apps\CoverageVerifier'
# for UNC paths
# change 'servername' to your actual servers name
$path = '\\servername\apps\CoverageVerifier'
$pathHeader = Join-Path -Path $path -ChildPath 'Header.txt'
$pathData = Join-Path -Path $path -ChildPath 'Data.txt'
$pathTrailer = Join-Path -Path $path -ChildPath 'Trailer.txt'
$dateStr = (Get-Date).ToString("yyyyMMdd")
$outFile = Join-Path -Path $path -ChildPath ($dateStr + "_TestVerifier.txt")
Get-Content $pathHeader, $pathData, $pathTrailer | Set-Content $outFile
As you can see, I'm using the Join-Path cmdlet a lot to make sure my file paths get concatenated correctly.
Why don't you use the format operator and Join-Path?
Edit even with only one format
$path = "\\xx\apps\CoverageVerifier"
$pathHeader = Join-Path $path "Header.txt"
$pathData = Join-Path $path "Data.txt"
$pathTrailer = Join-Path $path "Trailer.txt"
Get-Content $pathHeader,$pathData,$pathTrailer |
Set-Content (Join-Path $path ("{0:yyyyMMdd}_TestVerifier.txt" -f (Get-Date))
you use set-content to modify the content of a file, not the filename:
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/set-content?view=powershell-6

Copy and Rename Files Modified in Last Day Using Powershell

I am trying to copy over files from a source folder to a destination folder. I would like to only copy files that have been modified in the last 20 mins. While I am copying I would also like to append the date and time to the end of the file name. The script I currently have is:
$DestinationFolder = "C:\Output\"
$timespan = new-timespan -minutes 20
$Files = Get-ChildItem "C:\Input\*" -File
foreach ($File in $Files) {
if ($File.LastWriteTime -gt $timespan)
{
Copy-Item -Path $_.FullName -Destination $DestinationFolder$($_.BaseName)_$ ($_.LastWriteTime.ToString('yyyyMMdd_hhmmss'))$($_.Extension)
}
}
I am getting error messages in powershell when I attempt to test my scipt:
Could not compare "07/21/2017 07:31:01" to "00:20:00". Error: "Cannot convert the "00:20:00" value of type
"System.TimeSpan" to type "System.DateTime"."
At line:2 char:9
+ if ($File.LastWriteTime -gt $timespan)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : ComparisonFailure
You're comparing a DateTime with a TimeSpan. That doesn't make sense. A datetime is a point in time. A timespan is a duration. You need to compare two dates.
Try:
$DestinationFolder = "C:\Output\"
$Cutoff = (Get-Date).AddMinutes(-20)
Get-ChildItem "C:\Input\*" -File | Where-Object {
$_.LastWriteTime -gt $Cutoff
} | ForEach-Object {
$DestinationFileName = '{0}_{1:yyyyMMdd_HHmmss}{2}' -f $_.BaseName, $_.LastWriteTime, $_.Extension
$DestinationFullFileName = Join-Path -Path $DestinationFolder -ChildPath $DestinationFileName
Copy-Item -Path $_.FullName -Destination $DestinationFullFileName
}
I can't tell if there's a bug in your Copy-Item line or not. You may want a dollar sign and a space in there before the date, but I'm guessing that's not right.
According to the error you pasted Powershell is having trouble converting a System.TimeSpan to the type System.DateTime. Those are two different objects and you will have to cast one into the other before they will work together.