How to rewrite below code so it can be grouped into only one IF statements instead of multiple IF and only execute remove command if all files (outPath,outPath2, outPath3) are exists.
If ($outPath){
Remove-Item $outPath
}
If ($outPath2){
Remove-Item $outPath2
}
If ($outPath3){
Remove-Item $outPath3
}
If you want to be sure all the paths exist you can use Test-Path with -notcontains to get the results you want.
$paths = $outPath1, $outPath2, $outPath3
if ((test-path $paths) -notcontains $false){
Remove-Item -Path $paths
}
Test-Path works with arrays of paths. It will return an array booleans. If one of the paths didn't exist then a false would be returned. The if is conditional based on that logic.
Since you will only remove them if they exist you don't need to worry about their existence with the Remove-Item cmdlet.
this will remove the files if they exist and supress errors if the files are not found. The downside is that if there should be errors other than (path not found) then those would be supressed as well.
Remove-Item -Path $outPath,$outPath1,$outPath2 -ErrorAction SilentlyContinue
EDIT
if you only want to remove if all 3 files exist then:
if( (Test-Path $outPath) -and (Test-Path $outPath1) -and (Test-Path $outPath2) )
{
try
{
Remove-Item -Path $outPath,$outPath1,$outPath2 -ErrorAction Stop
}
Catch
{
throw $_
}
}
Related
I have some folder, the total of the folder is always different. Each folder has two file named as "ID" and "ID_DONE", for the file "ID_DONE" generate by other process. I want to remove file "ID" once "ID_DONE" generate to each folder.
I tried this, but I can not remove the "ID" file if I have more than one folder to check.
Anyone can help, please.
if(Test-Path -Path "$OpJob_Path\*\ID_DON"){
$Path_ID_DON = Get-ChildItem -Path "$OpJob_Path\*\ID_DON"
$Split = Split-Path -Path $Path_ID_DON
$Split
if(Test-Path -Path "$Split\ID")
{
Write-Host "Remove"
Remove-Item -Path "$Split\ID"
}
else{
Write-Host "Not Found"
}
}
else{
Write-Host "Continue..........."
}
Given that you're matching files across multiple directories with wildcard expression "$OpJob_Path\*\ID_DON", $Path_ID_DON will likely contain an array of files ([System.IO.FileSystem] items).
Therefore,
$Split = Split-Path -Path $Path_ID_DON
results in $Split containing an array of the parent-directory paths of the files stored in $Path_ID_DON.
If you want to remove a file named ID from all these directories, if present, use the following:
$Split | ForEach-Object {
$file = Join-Path $_ 'ID'
if (Test-Path $file) { Remove-Item $file -WhatIf }
}
-WhatIf previews the operation. Remove it once you're sure it will do what you want.
Something like this ?
Get-ChildItem "$OpJob_Path" -File -Filter "ID_DON" -Recurse | %{Remove-Item "$($_.DirectoryName)\ID" -ErrorAction SilentlyContinue}
I have some files in a folder. I want to rename the extension one by one. After I change the first extension file, I will do some process, then I come back again to change the next extension and do the process again.
I still can not figure out to rename it one by one, I only can rename all the files at the same time.
Function PICK_JOB
{
Write-Host "Pick 1st Job"
Get-ChildItem -Path C:\Users\F1 -File |
ForEach-Object { Copy-Item -Path $_.FullName -Destination "C:\Users\F1\$($_.BaseName).TXT" }
}
Function BEGIN
{
Write-Host "Creating"
& .\Folder.ps1 #execute a powershell script
Write-Host ">>>>>>Creating Finished<<<<<<"
}
#------------------------#
Function END
{
#Do some process
}
Function END_Proc
{
#Do some process
}
Function CHK
{
if($MLG -eq "1" -and $b_UB -eq "101")
{
Write-Host ">>>>>>BEGIN<<<<<"
BEGIN
PICK_JOB
}
if($MLG -eq "1" -and $b_UB -eq "444")
{
END
PICK_JOB
}
else
{
END_Proc
}
}
$MLG = "1"
$b_UB = "101"
$b = CHK
$A = BEGIN
Maybe i see something wrong but...
right now you are
changing extansion{}
Process{}
but you need to
Changing extansion{
Process{}
}
i hope this isn't wrong and you can get to your solution
Just to clarify what you are doing:
This is your code:
Get-ChildItem -Path C:\Users\F1 -File |
ForEach-Object { Copy-Item -Path $_.FullName -Destination "C:\Users\F1\$($_.BaseName).TXT" }
}
Get-ChildItem -Path C:\Users\F1 -File gets every -File in the -Path C:\Users\F1.
| ForEach-Object {} will do something with every single item that the former line returned.
Copy-Item ... -Destination "C:\...\$($_.BaseName).TXT" will copy the item $_ (which is the current item that is beeing proccessed) and rename it $($_.BaseName).TXT. That is (obviously) the BaseName + .TXT.
So yes you are renameing all of them in one step. If you want to process the items, you have to do it inside the ForEach-Object {}-block. If you want to rename them individually you have to filter them somehow with if statements inside the ForEach-Object {}-block or before you pipe (|) them into the ForEach-Object {}-block.
Will this work for you? All i did was rearrange ur existing function to a more comprehensible format.
Function PICK_JOB
{
Write-Host "Pick 1st Job"
Get-ChildItem -Path C:\Users\F1 -File |
ForEach-Object {
Copy-Item -Path $_.FullName -Destination "C:\Users\F1\$($_.BaseName).TXT"
<#call your process here#>
}
}
This will call ur other process after every file operation
Call your process function in given block to solve your problem
Get-ChildItem -Path C:\Users\F1 -File |
ForEach-Object {
Copy-Item -Path $_.FullName -Destination "C:\Users\F1\$($_.BaseName).TXT"
# CALL YOUR PROCESS FUNCTION HERE
}
I'm trying to copy files from a source folder to a destination folder, and rename the files in the process.
$Source = "C:\Source"
$File01 = Get-ChildItem $Source | Where-Object {$_.name -like "File*"}
$Destination = "\\Server01\Destination"
Copy-Item "$Source\$File01" "$Destination\File01.test" -Force -
Confirm:$False -ErrorAction silentlyContinue
if(-not $?) {write-warning "Copy Failed"}
else {write-host "Successfully moved $Source\$File01 to
$Destination\File01.test"}
The problem is that since Get-ChildItem doesn't throw an error message if the file is not found, but rather just gives you a blank, I end up with a folder called File01.test in destination if no file named File* exists in $Source.
If it does exist, the copy operation carries out just fine. But I don't want a folder to be created if no matching files exist in $Source, rather I just want an error message logged in a log file, and no file operation to occur.
This shouldn't matter what the file name is, but it won't account for files that already exist in the destination. So if there is already File01.txt and you're trying to copy File01.txt again you'll have problems.
param
(
$Source = "C:\Source",
$Destination = "\\Server01\Destination",
$Filter = "File*"
)
$Files = `
Get-ChildItem -Path $Source `
| Where-Object -Property Name -Like -Value $Filter
for ($i=0;$i -lt $Files.Count;$i++ )
{
$NewName = '{0}{1:D2}{3}' -f $Files[$i].BaseName,$i,$Files[$i].Extension
$NewPath = Join-Path -Path $Destination -ChildPath $NewName
try
{
Write-Host "Moving file from '$($Files[$i].FullName)' to '$NewPath'"
Copy-Item -Path $Files[$i] -Destination
}
catch
{
throw "Error moving file from '$($Files[$i].FullName)' to '$NewPath'"
}
}
You can add an "if" statement to ensure that the code to copy the files only runs when the file exists.
$Source = "C:\Source"
$Destination = "\\Server01\Destination"
$File01 = Get-ChildItem $Source | Where-Object {$_.name -like "File*"}
if ($File01) {
Copy-Item "$Source\$File01" "$Destination\File01.test" -Force -Confirm:$False -ErrorAction silentlyContinue
if(-not $?) {write-warning "Copy Failed"}
else {write-host "Successfully moved $Source\$File01 to
$Destination\File01.test"}
} else {
Write-Output "File did not exist in $source" | Out-File log.log
}
In the "if" block, it will check to see if $File01 has anything in it, and if so, then it'll run the subsequent code. In the "else" block, if the previous code did not run, it'll send the output to the log file "log.log".
I have a script that moves files around in a production environment and currently performs a copy-item, then test-path, followed by remove-item if the test-path worked ok, similar to the below:
if ($copySuccess -eq $true) {
$files = Get-ChildItem $fileDir -Filter $filePrefix*.*
$files | ForEach-Object {
if ($copySuccess -eq $true) {
Copy-Item $fileDir\$_ -Destination $destDir
if (!(Test-Path $destDir\$_)) {
$copySuccess = $false
}
}
}
}
This method makes me feel comfortable as the test-path guarantees that the file is where it needs to be, before removing it.
I'm planning to rewrite parts of the script and I'm wondering if by using a copy-item with a catch on error, I can be sure that if no error is seen that the file has definitely been copied to the destination (without the need to use test-path as I assume this would make it quicker). As in below:
Get-ChildItem $fileDir -Filter $filePrefix*.* | ForEach {
if ($copySuccess -eq $true) {
try {
Copy-Item $fileDir\$_ -Destination $destDir -ErrorAction Stop
}
catch {
$copySuccess = $false
}
}
}
}
Of course, if there is a better way, please let me know (Powershell v5). The reason for this level of checking is that there are often network issues on the infrastructure, hence the test-path currently in use.
ErrorAction won't work in this case since:
The ErrorAction parameter has no effect on terminating errors (such as
missing data, parameters that are not valid, or insufficient
permissions) that prevent a command from completing successfully.
[Source]
If you want to check whether Copy-Item worked you can do this in a couple of ways to make sure.
The first one is to use $? variable:
Errors and Debugging: The success or failure status of the last
command can be determined by checking $?
Copy-Item $fileDir\$_ -Destination $destDir
if(-not $?) {
Write-Warning "Copy Failed"
}
Another method is by using the -Passthru parameter, we can capture the results to a variable. Note, this variable will only be populated if the operation was successful:
if(-not Copy-Item $fileDir\$_ -Destination $destDir -PassThru) {
Write-Warning "Copy Failed"
}
This script will only delete files if all exists. How to rewrite the script, so it will delete files even one of the file is missing.
$paths = $outpath, $outPath2, $outPath3
if ((test-path $paths) -notcontains $false){
Remove-Item -Path $paths
}
If the problem is the error exception when it doesn't find a file , you can use the remove-item parameter -erroraction silentlycontinue :
$paths| % { Remove-Item "$_" -ErrorAction SilentlyContinue }