Powershell Archive script win2008r2 problems - powershell

I created a ps-script to move MS SCCM backup folder to another location and delete folders older than 2 days :
$Date = Get-Date -format d.M.yyyy
$BackupDir = "\\Source_Servername\Folder1\Folder2"
$ArchiveDir = "\\Destination_Servername\Folder1\Folder2"
set-alias 7za "$ArchiveDir\7za.exe"
Get-Item "$ArchiveDir\*" |? {$_.psiscontainer -and $_.lastwritetime -le (get-date).adddays(-2)} |% {remove-item $_ -Recurse -Confirm:$false}
7za a -r "$ArchiveDir\$Date\$BackupDir.7z" $BackupDir
I created this using Win 8 and when i try to apply it on win2008r2 servers it fails with the following error :
Bad numeric constant: 7.
At E:\xxxxx\xxxxx\xxxx\Afterbackup.ps1:9 char:2
+ 7 <<<< za a -r "$ArchiveDir\$Date\$BackupDir.7z" $BackupDir
+ CategoryInfo : ParserError: (7:String) [], ParseException
+ FullyQualifiedErrorId : BadNumericConstant
It works when i enter the full path to 7za.exe like this :
\Destination_Servername\Folder1\Folder2\7za a -r "$ArchiveDir\$Date\$BackupDir.7z" $BackupDir
I'm new to powershell so i would appriciate any help :)

PowerShell v1 & v2 do not like commands that start with numbers. The issue seems to have been addressed in v3 and that's probably why it works on your workstation. You can work around this by placing a backtick in front of the alias when you execute it:
`7za a -r "$ArchiveDir\$Date\$BackupDir.7z" $BackupDir
Alternately, you can change the alias to not start with a number.

Related

Remove certain characters from all folder names in a folder

I have a folder with a load of subfolders with a random number at the beginning of their folder name. they are in this format:
1254170-folder1
1212340-folder2
3245417-folder3
What can I to rename all of them to
folder1
folder2
folder3
I tried something like this because I saw something similar about filenames.
for f in *\1*;do( mv "$f" "${f//1/ }");done
but it does not work. the powershell returned
At line:1 char:4
+ for f in *\1*;do( mv "$f" "${f//1/ }");done
+ ~
Missing opening '(' after keyword 'for'.
At line:1 char:17
+ for f in *\1*;do( mv "$f" "${f//1/ }");done
+ ~
Missing statement body in do loop.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingOpenParenthesisAfterKeyword
Not sure what should I do. I am using Windows 10 2004.
Thanks for the help.
This should work:
Get-ChildItem -path . -directory -recurse | Where {$_.Name -match '^\d+-'} | Rename-Item -NewName {$_.Name -replace '^\d+-',''}
First command enumerates folders and all subfolders in current directory (.).
Second command filters folders which starts with digits followed by dash (^\d+- regex)
Third command renames the folders by removing ^\d+- prefix
I complet the #Renat code :
if you want exclude the directories with format without characters after the '-' (example 1254170- )
And if you want your script continue same if a directory with the new name already exist
Get-ChildItem "c:\temp\" -dir | where name -match "^\d+-.+$" | Rename-Item -NewName {$_.Name.Split('-')[1]} -ErrorAction SilentlyContinue

Powershell excluding only files

I have the following error when running a script in powershell in version 5.1
Below my simple script to delete files over 180 days, I've tried some solutions but I haven't found what may be the error.
(Below error translated from Portuguese to English)
"Out-File: It is not possible to validate the argument in the 'Encoding' parameter. The" files \ DeleteLogFile_21_01_2020.log "argument does not belong to the set" unknown; string; unicode; bigendianunicode; utf8; utf7; utf32; ascii; default; oem "specified by the ValidateSet attribute. Provide an argument that is in the set and try the command again. On the line: 1 character: 36 + $ Log | Out-File -Append D: \ Program files \ DeleteLogFile_ $ LogDate.log + ~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CategoryInfo: InvalidData: (:) [Out-File], ParameterBindingValidationException + FullyQualifiedErrorId: ParameterArgumentValidationError, Microsoft .PowerShell.Commands.OutFileCommand "
$logPath = "D:\Program files\NICE Systems\Logs"
$nDays = 10
$startTime = Get-Date
$Extensions = "*.*"
$LogDate = (Get-Date).ToString("dd_MM_yyyy")
$Files = Get-Childitem $LogPath -Include $Extensions -Recurse | Where-Object {$_.LastWriteTime -le (Get-Date).AddDays(-$nDays)}
foreach ($File in $Files)
{
if ($NULL -ne $File )
{
$Log = "`nData e Hora da Deleção: " + $startTime + ". O arquivo " + $File + " foi deletado do sistema."
$Log | Out-File -Append D:\Program files\DeleteLogFile_$LogDate.log
Remove-Item $File.FullName | out-null
}
}
You have no quotes around the path to your log file so it's cutting it off at the first space. You can use double quotes and the variable will still be expanded. Single will not be.
$Log | Out-File -Append "D:\Program files\DeleteLogFile_$LogDate.log"
By default windows will also not allow you to write to the program files folder and this is generally not good practice.
On your Out-File line, your path has a space in it and is not surrounded with quotation marks. In PowerShell, and most scripting languages for that matter, you have to take into account Positional Parameters. Any space that is not in a string or is not followed by/preceded by a parameter (eg. -FileName C:\FileName.txt), will be assumed to precede a positional parameter.
With that said, it is trying to use "D:\Program" as the path, and "files\DeleteLogFile_$LogDate.log" as the encoding type, which is obviously not valid. To fix this, simply make the path a string by putting it in quotation marks like so:
$Log | Out-File -Append "D:\Program files\DeleteLogFile_$LogDate.log"

powershell from chef resource powershell_script

I am trying to use one var declared outside chef resource powershell_script.
cn_name = powershell.exe hostname
puts cn_name ## will print like WIN-I5NP98N6JUE.cpteam.local
Now , i am trying to get the thumbprint of the root CA cert installed in this host.
powershell_script 'import CA_cert' do
code <<-EOH
$Thumbprint = (Get-ChildItem -Path Cert:\\LocalMachine\\Root | Where-Object {$_.Subject -match "CN="#{cn_name}""}).Thumbprint;
EOH
end
This is printing like : + ... ct -match "CN="WIN-I5NP98N6JUEcpteam.local""}).Thumbprint;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token 'WIN-I5NP98N6JUEcpteam.local""' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken
Kindly help me here how to escape those quotes./ before quotes doesnt work.
Thanks!
That should be {$_.Subject -match "CN=#{cn_name}"}), you don't need the extra quotes at all.
try this to escape your extra quotes:
$Thumbprint = (Get-ChildItem -Path Cert:\\LocalMachine\\Root | Where-Object {$_.Subject -match "CN=`"#{cn_name}`""}).Thumbprint;

How to zip / 7zip / or any other compress a list of files

I'm basically trying to do some basic log deleting operation
by several steps.
1st - get all the files that are older then X days (7 in my case)
2nd - zip them to a different location
3rd - delete the zipped files
4th - go over the folder of zipped logs and delete older then 30 Days
1st - accomplished - I get the list of files
3rd - not a problem - I think
4th - same as 1st ...
2nd ... here I try to use the 7zip as it is already embedded in Windows
we have strict policies regrading 3rd party tools
so winrar is not an option
this is the code I have tried but I don't get any results
it fails on the zip command
if ((Test-Path "$env:ProgramFiles\7-Zip\7z.exe") -eq $true){Set-Alias sz "$env:ProgramFiles\7-Zip\7z.exe" }
$DateStr = (Get-Date).ToString("dd-MM-yyyy")
$arcPath = "D:\SDDP\LOG_Archive_$DateStr.zip"
$limit = (Get-Date).AddDays(-7)
$path = "D:\SDDP\LOG"
$filesToBackUP = Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit }
ForEach ( $file in $filesToBackUP )
{
sz a -tzip $archPath $file.FullName
}
the error I get is :
Open archive: D:\SDDP\LOG\DISTRIBUTOR(232)\04-09-2015\SDDP_DISTRIBUTOR(232)_04-09-2015_1.csv
sz : ERROR: D:\SDDP\LOG\DISTRIBUTOR(232)\04-09-2015\SDDP_DISTRIBUTOR(232)_04-09-2015_1.csv
At line:13 char:9
+ sz a -tzip $archPath $file.FullName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (ERROR: D:\SDDP\...4-09-2015_1.csv:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
D:\SDDP\LOG\DISTRIBUTOR(232)\04-09-2015\SDDP_DISTRIBUTOR(232)_04-09-2015_1.csv
Open ERROR: Can not open the file as [zip] archive
ERRORS:
Is not archive
System ERROR:
Incorrect function.
Reference to the zip command I took from here
as I gone through the add reference there is nothing about creating a new 7zip file to add the files to, so I suppose it creates automatically but not so sure about it.
Please advice.
Thanks.
Try something along the lines of:
[string]$Zip = "C:\path to 7zip\7-zip\7z.exe";
[array]$args = "a", "-tzip", "-y", "-r", "$arcPath ";
ForEach ( $file in $filesToBackUP )
{
$Zip $args $file;
}
Sorry, I am currently on the move and unable to test this.
In PowerShell 5.0, there is an example below. You can replace dir .\dirToZip\* -File with a list.
dir .\dirToZip\* -File | %{
Compress-Archive -Path $_.fullname -DestinationPath .\test.zip -Update
}

Powershell WMI Query failing when executed from Task Scheduler

i have a strange problem...
i have the following code, which takes the output from Sysinternals Disk Usage tool (link below)
Disk Usage - Sys Internals
so first i get the physical drives into array $Disks, then i enumerate these through the foreach and mess about with them.
my problem lies in this line $Dir = du.exe -q -v $d.DeviceID
$PC = get-content env:COMPUTERNAME
$Disk = gwmi win32_logicaldisk -filter "drivetype=3"
foreach ($d in $Disk)
{
$Dir = du.exe -q -v $d.DeviceID
$Dir[8..($Dir.length-8)] | foreach {
$Size = $_.substring(0,10).replace(",","")/1024
$Path = $_.substring(10)
}
}
$d.DeviceID should be the drive letter (i.e. C:)
then i populate $Dir with the output from DU.exe, but $d.DeviceID is not acting how it is supposed to, running this from a task has this following result (added a line that says $d.DeviceID, to show the output):
B:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
C:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
D:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
running it from the ISE or just from the Shell has no issues, running it on other servers from all methods works.
i do believe the population of the $Dir vairable is the problem, as the du.exe has trouble with the $d.DeviceID
i dont understand why it is just this server/task sheduler that has the issue. i have tried the following:
redefined the array element to $i = $d.deviceID to fix it down - nothing
exported the job from other server (both DCs) an imported - nothing
restarted the winmgmt service - nothing
i think its a permissions issue, but im running this on an AD as THE Dom Admin with top privilages.
please can you guys help on this one, really am stuck...
cheers
Lee
Yet another update based on comment below:
Try:
$cmd = "du.exe `-q `-v $($d.DeviceID)"
$dir = Invoke-Expression $cmd
Updating as per the comment below.
Take this example. This can get the size of every folder and display size and full path to the folder.
Function Get-FolderSize {
Param ($folderPath)
$colItems = (Get-ChildItem $folderPath -recurse | Measure-Object -property length -sum)
return $colItems.sum/1MB
}
$folders = Get-ChildItem -Recurse C:\Scripts
$folders | % {
if ($_.PSIsContainer) {
$size = Get-FolderSize $_.FullName
Write-Host $size
Write-Host $_.FullName
}
}
You can use WMI to get the drive letter and pass it to the script. For example:
$disks = gwmi win32_logicaldisk -filter "drivetype=3"
$disks | % {
$items = Get-ChildItem -Recurse $_.DeviceID -Force
$items | % {
if ($_.PSIsContainer) {
$size = Get-FolderSize $_.FullName
Write-Host $size
Write-Host $_.FullName
}
}
}
So, with this, you dont need DU.exe. You can run this as a script.
--------------OLD ANSWER _-------------------
First thing I would suspect is the path to DU.exe. What is the working directory set on the scheduled task? Is it the place where DU.exe is available?
BTW, what is the goal of this script? Are you just looking at the disk drive size? What are you capturing into $path? I did not have the patience to test your code. But, I feel that this can be easily achieved using just WMI and no other external tools.