Array handling in powershell - powershell

Context :
I have a folder and have some files inside it. I am running a PowerShell script from Jenkins to delete the list of files selected from Jenkins and copy the fresh file from the source. I am trying to delete the files all at an time and copy the list of files like Ctrl+A and copy and paste. I have the script but it is doing individual deletion and copy-paste.
foreach ($database_filename in $database_files) {
Remove-Item -Path $auditFile_Directory -Include $database_filename* -Recurse -Force
Remove-Item -Path $logFile_Directory -Include $database_filename* -Recurse -Force
if ($?) {
log "Deleting the old files complete."
}
try {
log "File sets for $database_filename copying...."
$primary_File = "$database_filename$primaryfile_extn"
$audit_Files = "$database_filename$auditfile_extn"
$log_Files = "$database_filename$logfile_extn"
Copy-Item -Path $sourceFile_Directory$primary_File -Destination $auditFile_Directory
Copy-Item -Path $sourceFile_Directory$audit_Files -Destination $auditFile_Directory
Copy-Item -Path $sourceFile_Directory$log_Files -Destination $logFile_Directory
if ($?) {
log "A fresh golden copy of the db files created."
} else {
Write-Error "Failed! error creating the golden copy, please check the log files"
}
}
catch [System.Net.WebException], [System.IO.IOException]
{
Write-Error "Failed! Unable to copy the SQL files"
}
}
}

You need to split the code into two loops then, the first loop will delete all the files and the second loop will copy all the files.

Related

Powershell : Search the Subdirectory and copy the file to that directory

I have been working on a Powershell script from past 2 weeks and I haven't made much progress in that.
So I'm trying to copy a file called version.properties from the root of my gradle project to the Subdirectories like "src/main/resources", "src/main/webapp" and "src/main/application".
If i hard code the path it's working, but im trying to make it generic by finding the directory and copying my file to that directory.
I want my version.properties file to be copied to "resources","webapp" and "application" directory after i run my powershell script.
How can i do it? Any suggestions are appreciated.
$SourceDirectory = "Projectroot\version.properties"
$folders = gci $SourceDirectory -Recurse -Directory
$jar = "src/main/resources"
$ear = "src/main/application"
$war = "src/main/webapp"
foreach ($folder in Sfolders) {
if (Test-Path $folder/$jar) {
write-host "copying to $folder/$jar"
Copy-Item-Path "{$SourceDirectory}\version.properties" -Destination $folder/$jar -Recurse -Force
}
elseif (Test-Path $folder/$ear) {
write-host "copying to $folder/$ear"
Copy-Item-Path "{$SourceDirectory}\version.properties" -Destination $folder/$ear -Recurse -Force
}
elseif (Test-Path $folder/$war) {
write-host "copying to $folder/$war"
Copy-Item-Path "{$SourceDirectory}\version.properties" -Destination $folder/$war -Recurse -Force
}
else {
Write-Host "No such path"
}
}
Assuming this is the path structure of a project:
#ProjectRoot
#ProjectRoot\version.properties <--- File
#ProjectRoot\src
#ProjectRoot\src\main
#ProjectRoot\src\main\application
#ProjectRoot\src\main\resources
#ProjectRoot\src\main\webapp
The following script will do what you seek.
$SourceDirectory = "C:\temp\Projectroot"
$DestinationDirectories = 'resources','application','webapp'
foreach ($I in $DestinationDirectories) {
$CurrentDest = "$SourceDirectory\src\main\$I"
if (Test-Path -Path $CurrentDest) {
Copy-Item -Path "$SourceDirectory\version.properties" -Destination $CurrentDest
} else {
Write-Warning "Path not found: $CurrentDest"
}
}
If I didn't get the path structure, please clarify which is it.
I am assuming too that "main" is a static keyword here but if it is not, that script might need to be adjusted to reflect that.

Error on Move-Item moving home area to file server

This is the last section of my script that I use to transfer student leavers areas to an archive file server. The script runs and does everything as expected but still throws an error out saying
Move-Item : Cannot find path '\\domain\students$\E-J$\MH201507' because it does not exist. The script does find this path and moves the home area so I'm not sure why I get this error. Or is there any way to fix this or is it easier to hide the error somehow?
The CSV document contains a list of the sam account name and contains their home area location on the domain so it knows where to copy the path over from.
Any help would be massively appreicaited! Kind Regards
#Declaring the .csv file that contains a list of all leavers home directories.
$HomeDirectoryList = Import-CSV "C:\Scripts\Leavers\HomeDirectoryExport.csv"
$Username = $HomeDirectoryList.samAccountName
$HomeDirectory = $HomeDirectoryList.HomeDirectory
$Archive = "\\myfileserver.ac.uk\D$\21-22 Leavers"
ForEach ($Username in $HomeDirectoryList)
{
Move-Item -Path $HomeDirectory -Destination $Archive
}
Sample data with which the error occurs:
samAccountName HomeDirectory
WB214589 \\domain\students$\A-D$\WB214589
MH201507 \\domain\students$\E-J$\MH201507
You are setting the variable $HomeDirectory outside the loop, so that will contain an array of home directory paths.
Then you use variable $Username to iterate the data from the CSV file, but inside that loop you never use it.
Try:
$HomeDirectoryList = Import-CSV 'C:\Scripts\Leavers\HomeDirectoryExport.csv'
$Archive = '\\myfileserver.ac.uk\D$\21-22 Leavers'
foreach ($student in $HomeDirectoryList) {
Write-Host "Moving HomeDirectory folder for student '$($student.samAccountName)'"
Move-Item -Path $student.HomeDirectory -Destination $Archive -Force
}
If you need to catch errors happening, change the loop to:
foreach ($student in $HomeDirectoryList) {
Write-Host "Moving HomeDirectory folder for student '$($student.samAccountName)'"
try {
Move-Item -Path $student.HomeDirectory -Destination $Archive -Force -ErrorAction Stop
}
catch {
Write-Warning "Error moving homedirectory '$($student.HomeDirectory)':`r`n$($_.Exception.Message)"
}
}

script file, wait function until end of generation files

I have a script file (batch file) which generate three files in a specific folder. Then i have a ps1 file which copy / move the generated files to another server / folders. Separately, everything is working properly
I'd like if it's possible to merge this, and have a wait function between the two scripts. In fact launching the copy / move ps1 function, only when the three files was correctly generated.
The following assumes:
that the files are created and written in full in a single operation.
that it is the appearance of a *.zip file that signals that all files of interest have been created (though they may still in the process of being written to), as you've indicated in a later comment.
$inFolder = '.' # set to the folder of interest.
$outFolder = './out' # ditto
Write-Verbose -vb 'Waiting for a *.zip file to appear...'
while (-not (Test-Path "$inFolder/*.zip")) { Start-Sleep 1 }
# Get a list of all files.
$files = Get-ChildItem -File $inFolder
Write-Verbose -vb 'Waiting for all files to be written completely...'
$files | ForEach-Object {
do {
# Infer from the ability to obtain an exclusive lock that the file has
# has been written in its entirety.
try { [IO.File]::Open($_.FullName, 'Open', 'Read', 'None').Dispose(); return }
catch { Start-Sleep 1 }
} while ($true)
}
# Move the files elsewhere
Write-Verbose -vb 'Moving...'
$files | Move-Item -Destination $outFolder -WhatIf
Note: The -WhatIf common parameter in the last command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.
param(
[String]$sourceDirectory = "c:\tmp\001",
[String]$destDirectory = "c:\tmp\001"
)
Get-ChildItem $sourceDirectory | ? {
#this step wait while locks free
[bool]$flag
while (!$flag) {
try {
$FileStream = [System.IO.File]::Open($_,'Open','Write')
$FileStream.Close()
$FileStream.Dispose()
$flag = $true
}
catch{
Start-ScheduledTask -s 1
$null
}
}
$true
} | Copy-Item -Destination $destDirectory

Perform file verification check with Copy-Item

The following script creates a folder named the specified date on the servers in servers.txt, then copies the folder from which the script is run to that folder.
For example, it creates the folder "3-22-15 (night)" on SERVER1, SERVER2, etc., then copies "Directory Containing the Script" to "3-22-15 (night)".
$CurrentLocation = get-location
$DeploymentDate = "3-22-15 (night)"
Foreach($server in get-content "servers.txt"){
New-Item -ErrorAction SilentlyContinue -ItemType directory -Path \\$server\C$\Deployments\$DeploymentDate
copy-item -Path $CurrentLocation -Destination \\$server\C$\Deployments\$DeploymentDate\ -ErrorAction SilentlyContinue -recurse
}
How do I modify the script to include file verification for each file that is copied to \\$server\C$\Deployments\$DeploymentDate\?
I would like it to output an error message with the file that does not pass the verification check, but to continue copying.
I was going to try something like this:
function SafeCopy ($SourcePath,$DestinationPath,$SourceFileName) {
#MD5 Check Function
function Check-MD5 ($FilePath) {
$md5=New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash=[System.BitConverter]::ToString($md5.ComputeHash([System.IO.File]::ReadAllBytes($FilePath)))
Return $hash
} # EndOf function Check-MD5
$MD5Source=Check-MD5 $SourcePath
Copy-Item $SourcePath\$SourceFileName $DestinationPath
$MD5Destination=Check-MD5 $DestinationPath
if (Test-Path $DestinationPath) {
if ($MD5Destination -match $MD5Source) {
Write-Host "`nThe file `"$SourcePath`" has been copied in `"$DestinationPath`" successfully.`n" -ForegroundColor DarkGreen
} else {
Write-Host "`nThe file `"$SourcePath`" has been copied in `"$DestinationPath`" but the CRC check failed!`n" -ForegroundColor DarkRed
}
} else {
Write-Host "`nThe file `"$SourcePath`" has not been copied in `"$DestinationPath`"!`n" -ForegroundColor DarkRed
}
} # EndOf function SafeCopy
But I'm not sure how to implement it.
I am not a talented scripter nor do I play one on the radio but I've put this together and it seems to work. As mentioned, the larger the filesize being compared, the slower it goes.
Param
(
[parameter(Mandatory=$true,Position=1,ValueFromPipeLine=$true)][string]$source,
[parameter(Mandatory=$true,Position=2,ValueFromPipeLine=$true)][string]$dest
)
$countsource = #(Get-ChildItem -Path $source -Directory)
$countdest = #(Get-ChildItem -Path $dest -Directory)
IF($countsource = $countdest){
"$source equals $dest"
}
Else{
"$source does not match $dest"
}
Sample usage and output. TODO: Add folder item count compare, warn or break if the folders do not have the same number of items (subfolders and files).
So copy the folder then run Folder-Compare as a function once the copy is finished.
PS C:\Scripts> .\Folder-Compare.ps1 -source C:\Scripts\temp -dest C:\aaa
C:\Scripts\temp does not match C:\aaa

How many ways to check if a script was "successful" by using Powershell?

I am still very new and I have for example one script to backup some folders by zipping and copying them to a newly created folder.
Now I want to know if the zip and copy process was successful, by successful i mean if my computer zipped and copied it. I don't want to check the content, so I assume that my script took the right folders and zipped them.
Here is my script :
$backupversion = "1.65"
# declare variables for zip
$folder = "C:\com\services" , "C:\com\www"
$destPath = "C:\com\backup\$backupversion\"
# Create Folder for the zipped services
New-Item -ItemType directory -Path "$destPath"
#Define zip function
function create-7zip{
param([String] $folder,
[String] $destinationFilePath)
write-host $folder $destinationFilePath
[string]$pathToZipExe = "C:\Program Files (x86)\7-Zip\7zG.exe";
[Array]$arguments = "a", "-tzip", "$destinationFilePath", "$folder";
& $pathToZipExe $arguments;
}
Get-ChildItem $folder | ? { $_.PSIsContainer} | % {
write-host $_.BaseName $_.Name;
$dest= [System.String]::Concat($destPath,$_.Name,".zip");
(create-7zip $_.FullName $dest)
}
Now I can either check if in the parentfolder is a newly created folder by time.
Or i can check if there are zip folders in my subfolders I created.
What way would you suggest? I probably just know this ways, but there are a million way to do this.
Whats your idea? The only rule is , that powershell should be used.
thanks in advance
You could try using the Try and Catch method by wrapping the (create-7zip $_.FullName $dest) with a try and then catch any errors:
Try{ (create-7zip $_.FullName $dest) }
Catch{ Write-Host $error[0] }
This will Try the function create-7zip and write any the errors that many accrue to the shell.
One thing that can be tried is checking the $? variable for the status of the command.
$? stores the status of the last command run,
So for
create-7zip $_.FullName $dest
If you then echo out $? you will see either true or false.
Another option is the $error variable
You can also combine these in all sorts of ways (Or with the exception handling).
For example, run your command
foreach-object {
create-7zip $_.FullName $dest
if (!$?) {"$_.FullName $ErrorVariable" | out-file Errors.txt}
}
That script is more pseudocode for ideas than working code, but it should at least get you close to using it!