Powershell move-item does not remove some 3D png files from source - powershell

I have a Powershell script issuing the Move-Item command to move some 3D CAD directories and subdirectories from one network share to another. About 300 parent folders a day. I am having the most strange problem. All parent folders are copying to the destination just fine, but about 10 of the 300 objects are not being removed from the source. It seems that any subdirectory that contains a type of png scan file, will not remove from the source; it copies fine, just doesn't remove from source. No error is reported in the -verbose log output. The file sizes are not large, < 50MB each. Doing some testing, I also noticed that if I run the script once, the problem occurs, but if I run the script again with no changes, it moves the remaining objects that it did not move on the initial run. Another observation is that if I run the script where the source and destination are on the same share, the problem does not occur. The problem only occurs when source and destination are on different shares. Same problem using both versions 5.1 and 4.0.
I also tried using some simple png files I created myself just by saving a jpg screen print as a png, and those png files copy and remove fine. So something is special about these 3D CAD png files. I even tried copying off the parent folder to share to make sure no one or no program is locking the original files, and the problem still happens.
I have been successful at replacing the move-item command with a robocopy command, and it works perfectly, so I could use robocopy to solve my problem, but I want to figure out why the move-item command is having this problem. My only theory is that if on the same share, no data is actually being moved, only the reference to the file, ie pointer, ie FAT (file allocation table) is being changed. When crossing shares the actual file data has to be moved, so something is funny about these files that prevents that from happening. But as stated above, if I run the script a 2nd time, the remaining files copy and remove fine. So that leaves a little unexplained.
Just wondering if anyone has any ideas.
See the code samples below, and also some screen prints of the source folder structure before and after.
$sLogPath = 'C:\PowerShell_scripts\test\robocopy_test.log'
$StagingFolder = '\\3ipbg-fs-p01\PSP_Inbound\Test\3Shape_Auto_Create\Suspense\test_case_01'
$FinalFolder_M = '\\3ipbg-fs-p01\patient specific mfg\3Shape_AutoCreate\Auto_Job_Create_Test\Inbox_Manual_Jobs'
$FinalFolder_M_robo = '\\3ipbg-fs-p01\patient specific mfg\3Shape_AutoCreate\Auto_Job_Create_Test\Inbox_Manual_Jobs\test_case_01'
Move-Item -LiteralPath $StagingFolder $FinalFolder_M -Verbose -Force
robocopy $StagingFolder $FinalFolder_M_robo /R:3 /W:3 /E /B /J /MIR /MOVE /LOG+:$sLogPath
enter image description here

You are using /R:3 parameter for robocopy, meaning it retries to move the folder up to 3 times if an error is present.
I am not aware of such functionality in PowerShell, but you could easily write a small utility function for this.
Assumptions:
1) In the loop code, it checks if the source folder exists, if Yes, it continues up to $retries times with Sleep of 2 seconds.
Function Custom-Move{
param( [string]$source, [string]$destination, [int]$retries)
$i=0
while($i -ne $retries){
Move-Item -LiteralPath $source -Destination $destination -Verbose -Force -ErrorAction SilentlyContinue
#test if the folder exist, if not meaning that the folder was moved.
if(-not (Test-Path $source)) {break}
$i++
Start-Sleep 2
}
}
Usage:
Custom-Move $StagingFolder $FinalFolder_M 5

Related

Powershell Cannot create a file when that file already exists when using Move-Item

I'm trying to move png images in subfolders to a subfolder in the folder they are in.
Main folder is called "stuff", images are in variously named subfolders in the "stuff" main folder, and each of these subfolders have a folder name "Oneshot" in them, I'm trying to move these images that are in M:/Stuff/FolderExample/ to M:/Stuff/FolderExample/Oneshot/.
Current code I am using
Get-ChildItem -Path C:\Users\a\Desktop\stuff\*.png -Recurse | Move-Item -Destination "$($_.FullName)\Oneshot\"
How can I make this work? I'm just trying to learn powershell so I can automate this process as I otherwise would need to repeat the process manually for thousands of times
Use a scriptblock ({...}) as the argument to -Destination - this will allow you to access the current pipeline item as $_ during parameter binding:
Get-ChildItem -Path C:\Users\a\Desktop\stuff\*.png -Recurse |Where-Object Directory -notlike *\OneShot | Move-Item -Destination {"$($_.Directory.FullName)\Oneshot\"}
The Where-Object command in the middle of the pipeline will ensure we don't attempt to move pictures already in one of the OneShot folders.
Powershell is not the best idea to move files. The main reason is that you run into problems in case the path becomes too long >256 characters. I would use robocopy for such tasks. It is part of every current windows version.
robocopy M:/Stuff/FolderExample/ M:/Stuff/FolderExample/Oneshot/ /MIR
Please keep in mind that this code will also delete everything that is in M:/Stuff/FolderExample/Oneshot/ and not in M:/Stuff/FolderExample/. So use /MIR with caution.
You could still invoke robocopy in an ps1 file and wrap other powershell code around it e.g. for variables.

Copy-item cmdlets only working correctly when the destination folder exists

I want to copy folders with their contents to a remote computer using a PSSession and Copy-item. When running the script for the first time it has to create the destination folder, it does so correctly and then is supposed to dump the folders with their contents inside into the destination folder. What it is instead doing is dumping two of the folders correctly and then dumping the contents of the third folder, not the folder itself. When I run it a second time without deleting the destination folder, everything runs fine.
I have tried using various different parameters, including -container but it doesn't seem to help at all. Here is where I use the function in my code, I use a lot of environment variables and variables in general because this needs to be a script that can be put anywhere and work.
if (Test-Path -path "$env:TEMP\VMlogs") {
Write-Host "I'M GONNA SEND IT!"; Pause
Copy-Item -path "$env:TMP\VMLogs\*" -tosession $Targetsession -destination $Destination`_$Source -force -recurse
Write-Host Logs copied sucessfully!
Remove-Item "$env:TEMP\VMlogs" -recurse
} else {
Write-Host "There was an issue copying logs!"
Pause
Exit
What I expect is that the folders are put into the destination folder with their intact structure but instead this only happens on the second running of the script, after the destination folder has already been created.

PowerShell Copy-Item not copying all files

I have a strange issue with the Copy-Item in PowerShell. Below you see two almost identical lines of code, only the source and destination is different.
Copy-Item "A:\*" -Destination "B:\" -Recurse -Force -Verbose -Confirm:$false -ErrorAction SilentlyContinu
Start-Sleep 3
Copy-Item "B:\*" -Destination "D:\" -Recurse -Force -Verbose -Confirm:$false -ErrorAction SilentlyContinu
These lines are a part of a script. It first notes the date and creates a log file and then it clears the B and D drive. After that, it starts copying. The first one, the Copy-Item A:\ to B:\ works, it copies everything.
When PowerShell gets to the second one, it only copies a few folders and just skips over the remaining folders. It doesn't throw me an error or anything.
When I manually execute the second line, it works, but not when it's in a script.
What is wrong here?
I'd use robocopy for this, it's included in all modern versions of windows and is very powerful and can complete pretty much any copy function you want.
ROBOCOPY /MIR <Source> <Target>
/MIR is the mirror switch. It will both copy source to target and delete anything in target that isn't present in source. Leaving target as a mirror copy of source.
You might also want to look into the /MT multi-thread switch to speed things up if the directories contain a large number of files.

Copying group of folders, first in line get's it's contents spilled in the open

I want to copy a group of folders which have various files inside them from one place to a single folder elsewhere. I want to bind said folder group to a variable.
param(
$folders=('../folder1','../folder2')
)
Copy-Item -Path $folders -Destination '../folder3' -Recurse -Force;
This works, however, inside folder3, folder1's contents are spilled out, while folder2's contents are placed in a folder of the same name just like intended.
I need them both to be copied intact, if I switch their places then folder2 gets the same treatment. It's like the script does not read the first folder in line in same way as the others. Am I missing something?
EDIT:
Managed to find a work-around by running additional command to create a folder inside "folder3" named same as first in line folder before copying. Script then places the files inside that folder correctly. Still rather messy, I wonder if it's a bug.
Use a loop
foreach($folder in $folders){
Copy-Item -Path $folder -Destination '../folder3'-Recurse -Force
}

Copy Script Trouble

I've created a script that I found in other forums to copy a file from one server to another. A bit of background here. We have large PDF files being generated nightly and saved on a share at one site that need to be copied over to our corporate share. These files are pretty sizable (anywhere between 25MB to as high as 65MB), so I can only copy these files off hours. The source repository holds all the original files from the year, so I only want to copy the most recent files. I created a script (or tried to at least) that copies only the most recent files from the SourceHost location to CorpHost share and set up a Task Schedule to run at 7:30pm.
The script kicks off and runs as scheduled, but nothing gets copied over. I don't see any errors being generated from the task schedule and it appears to run as normal as the script returns a "not copying .pdf". Originally, I though that maybe it was bypassing all the files because the generation date is outside the $Max_days range (-1), so I increased it to -2. No luck. Increased it again to -5 - no luck. -10... nothing.
Here's the code sample:
$RemotePath = "\\<CorpHost>\Shared\Packing_Slips\<Site>"
$SourcePath = "\\<SourceHost>\<Site>_packingslips"
$Max_days = "-1"
$Curr_date = Get-Date
#Checking date and then copying file from RemotePath to LocalPath
foreach ($file in (Get-ChildItem $SourcePath))
{
if ($file.LastWriteTime -gt ($Curr_date).AddDays($Max_days))
{
Copy-Item -Path $file.FullName -Destination $RemotePath
}
else
{
"not copying $file"
}
}