Copy-Item gets IOException when copying to the destination - powershell

I'm getting an IOException when Copy-Item copies files to the destination even though the destination is clean. Meaning there are no files in the destination before the copy proceeds. The odd thing is that it does not throw the error with all the files and the file it had an issue with copying does get copied. I'd be a lot easier if it just didn't work.
The code used to do the copying does it such a manner that it creates the current directory structure of the source path at the destination location.
Get-ChildItem $SourcePath -Recurse -Include "$FilePattern" | Foreach-Object {
$destDir = Split-Path ($_.FullName -replace [regex]::Escape($SourcePath), $dstfolder)
if (!(Test-Path $destDir)) {
New-Item -ItemType directory $destDir -ErrorAction SilentlyContinue | Out-Null
sleep 1
}
Copy-Item $_ -Destination $destDir -Force -ErrorAction Ignore -Verbose | Write-Output
}
The actual error message is
VERBOSE: Performing operation "Copy File" on Target "Item: \\EPM111242ND\C$\
HypStaging\Objects\Applications\Vision\Plan1\Plan1.otl Destination:
C:\Users\epmadmin\Documents\Backups\Monday\Full\Objects\Applications\Vision\
Plan1\Plan1.otl". The process cannot access the file 'C:\Users\epmadmin\
Documents\Backups\Monday\Full\Objects\Applications\Visio n\Plan1\Plan1.otl'
because it is being used by another process.
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : localhost
It seems to be the destination file that its having an issue with which doesn't exist until it gets copied. Oddly the file is there when I check it. So I tried -ErrorAction SilentlyContinue and -Ignore and both still produce the error message. I was think of maybe putting in a try catch statement but I'm not sure that'll suppress the message.

try this
Get-ChildItem $SourcePath -Recurse -Include "$FilePattern" | % {
$destDir = Split-Path ($_.FullName -replace [regex]::Escape($SourcePath), $dstfolder);
New-Item -ItemType directory $destDir -Force;
Copy-Item $_.fullname -Destination $destDir -Force
}

Related

Powershell access Denied

I've got this function, that move a directory to inside another directory, but always gives me the access denied error.
Any idea what am i doing wrong?
Get-ChildItem C:\Scripts\MetadataExport -Directory | ForEach-Object {
# this will look for a 4-12 digit number in the directory name
If ($_.Name -match '(?:\b|\D)(\d{4,12})(?:\b|\D)') {
$destPath = Join-Path $_.Parent.Fullname $Matches[1]
If (-not (Test-Path -LiteralPath $destPath)) {
New-Item $destPath -ItemType Directory
}
Move-Item -LiteralPath $_.Fullname -Destination $destPath -Force
}
}
the error:
Move-Item : Access to the path 'C:\Scripts\MetadataExport\kwakwala-rosenblum-0172' is denied.
At C:\Users\User\Documents\ScripsPS1\MetadataExport.ps1:170 char:9
Move-Item -LiteralPath $_.Fullname -Destination $destPath -Fo ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : WriteError: (C:\Scripts\Meta...-rosenblum-0172:DirectoryInfo) [Move-Item], IOException
+ FullyQualifiedErrorId : MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand
So, the goal is to move every folder that part of the name matches with another folder with numeric name.
Ex:
The 'kwakwala-rosenblum-0172' folder needs to move to inside '0172' folder.
Just move if the Literal-Path is the same as folder's name.
I am not sure what you are trying to do but you effectively try to move a folder to a folder with the same name:
$Null = New-Item -Path .\0172 -ItemType Directory -Force
$Null = New-Item -Path .\kwakwala-rosenblum-0172 -ItemType Directory -Force
Get-ChildItem -Directory | Foreach-Object {
if ($_.Name -Match '(?:\b|\D)(\d{4,12})(?:\b|\D)') {
$destPath = Join-Path $_.Parent.Fullname $Matches[1]
Write-Host $_.Fullname '-->' $destPath
}
}
C:\..\0172 --> C:\..\0172
C:\..\kwakwala-rosenblum-0172 --> C:\..\0172
Which is the same as doing this:
Move-Item -LiteralPath .\0172 -Destination .\0172 -force
Move-Item: The process cannot access the file because it is being used by another process.
Meaning that this would likely "resolve" the issue:
if ($_.Fullname -ne $destPath) {
Move-Item -LiteralPath $_.Fullname -Destination $destPath -Force
}
But, I am not sure what your expectation is.
You might want to explain (in the question) how you expect the subfolders to be (re)named.

I have an issue with using Copy-Item and a Veriable for destination

This Might be an easy one. But I can figure out what is going wrong with my simple copy script.
I have a shared directory that I am copying items from. I am printing out the destination path to console so I know it is correct But I am receiving a powershell error I do not understand.
Here is my script
#Files to copy
#Get Installers from folder
$APPS = Get-ChildItem \\Server1\shared\APPS -Name
#ForEach loop to identify and move files
ForEach($APP in $APPS) {
$dest = "\\Server1\Shared\APPS\$APP"
#Write-host to see destination path on console
write-host $dest
#copy item from destination path to local directory
Copy-Item $dest -Destination "c:\apps\"
}
This seems straight forward. But I don't understand why I am receiving the following error
\\Server1\Shared\APPS\LTCDesktopSetup.exe
Copy-Item : The filename, directory name, or volume label syntax is incorrect.
At C:\Users\computer1\documents\PowerShell\Moving Installer to local drive.ps1:13 char:2
+ Copy-Item $dest -Destination "c:\apps\"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
Augusto,
I'd suggest this syntax:
$APPS = (Get-ChildItem "\\mybooklive\CMShared\NAS-Downloads" -filter *.exe).FullName
ForEach ($App in $Apps) {
copy-item "$APP" -Destination "G:\Test\Copy-Test" -Force
}
or the more compact:
$APPS = (Get-ChildItem "\\mybooklive\CMShared\NAS-Downloads" -filter *.exe).FullName |
copy-item -Destination "G:\Test\Copy-Test" -Force
Getting FullName vs Name so you don't have to add the source path back in.
Using -Filter so you only get .exe files (this is an assumption from the variable name $Apps).
The force will take care of some IO problems like the file already existing.
HTH
Naturally, you'll have to substitute your paths for my test ones.

Moving folders with the files with exceptions

I'm trying to move data from the "file" folder and exclude the Users folder. but in the end, the exception does not work.
Move-Item -Path $env:SystemDrive\$env:computername\File\* -exclude $env:SystemDrive\$env:computername\File\Users\* -Destination $env:SystemDrive\UserOld\
It is necessary to transfer the data and exclude the Users folder.
I tried using move-item in order to move folders while excluding a single folder and it doesnt seem like you need to include the entire path in the exclude.
I tried this:
Move-Item -Path C:\Users\D.Baier\Desktop\testenvironment\Source -Exclude mit-1 -Destination C:\Users\D.Baier\Desktop\testenvironment\Target\
and it seemed to work perfectly, just threw an error which seems to be a known issue, at least as far as I understand it.
The error was the following btw:
Move-Item : The Element cannot be moved, since the Element, located at "C:\Users\D.Baier\Desktop\testenvironment\Source\mit-1" does not exist.
In Line:1 Charakter:1
+ Move-Item -Path C:\Users\D.Baier\Desktop\testenvironment\Source \* -Exclu ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Move-Item], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.MoveItemCommand
Hope that was helpful!
Edit: Sorry, my PC is set to German. I translated the error message as well as I can, however I doubt it is the exact same one one would get if you were to run this code on an English machine. I also apologize for any spelling mistakes I may have made.
First thing I want to touch on is how you're creating your paths. You shouldn't create them the way you are, you should instead use the Join-Path command :)
This is how I might approach your current problem:
#Creating path to source folder
$source = Join-Path -Path "$env:SystemDrive\$env:COMPUTERNAME" -ChildPath "File"
#Creating path to destination folder
$destination = Join-Path -Path $env:SystemDrive -ChildPath "UserOld"
#Looping through all the folders in the source
Get-ChildItem -Path $source -Directory -Recurse | ForEach-Object{
#Only moving the folder if the name isn't "Users"
if ($_.Name -ne "Users"){
Write-Host "Currently Moving: $_.Name"
#Copy-Item -Path $_.FullName -Destination $destination
}
}
Let me know how you get on, I've left the actual moving part commented out as I would encourage you to do more testing :)
carelessness
#Creating path to source folder
$source = Join-Path -Path "$env:SystemDrive\$env:COMPUTERNAME" -ChildPath "\File\C$\"
#Creating path to destination folder
$destination = Join-Path -Path $env:SystemDrive -ChildPath "UserOld"
$h = "Users", "Windows", "ProgramData"
#Looping through all the folders in the source
Get-ChildItem -Path $source -Recurse | ForEach-Object{
#Only moving the folder if the name isn't "Users"
if ($_.Name -ne "$h"){
Write-Host "Currently Moving: $_.Name"
}
Move-Item -Path $_.FullName -Exclude $h -Destination $destination
}
This option moves the Users folder without content.
For this reason, the combined answers.
#Creating path to destination folder
$destination = Join-Path -Path $env:SystemDrive -ChildPath "UserOld"
#Move with the exception
Move-Item -Path $env:SystemDrive\$env:computername\USMT\File\C$\* -Exclude "Users", "Windows","ProgramData","Program Files","Program Files (x86)" -Destination $destination

Copy Files on Same Directory using Powershell

I am trying to write powershell Script which will create backupfolder on same Path where Application exist and need to copy the folders & files into backupfolder before deploying. Below are the command was using to perform but am getting error
$Source = "C:\XYZ"
$BackupFolder = New-Item -ItemType Directory -Force -Path $source_$(Get-Date)
Copy-Item -Path $Source\* $BackupFolder -Force
Error: Cannot copy item C:\XYZ\Backup_18-02-2017 on to itself
Try:
Copy-Item $Source\* $BackupFolder -Exclude $BackupFolder
That will eliminate the folder that you are copying into as a source that is being copied from.
Variables can contain underscores. The following works and displays the string "asdf"
$a_ = "adsf"; $a_
Your New-Item cmdlet call should have failed since $source_ is not a variable and would return null. This is default behavior for PowerShell. When I run your code as is I get the following:
New-Item : Cannot find drive. A drive with the name '02/18/2017 22' does not exist.At line:1 char:1
+ New-Item -ItemType Directory -Force -Path "$source_$(Get-Date)" -what ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (02/18/2017 22:String) [New-Item], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.NewItemCommand
So I would have expected your folder variable to be null. wOxxOm brings this up in comment as well
Several options to address what I am sure is the partial source of your issue.
$BackupFolder = New-Item -ItemType Directory -Force -Path "$source`_$(Get-Date)"
$BackupFolder = New-Item -ItemType Directory -Force -Path "$($source)_$(Get-Date)"
$BackupFolder = New-Item -ItemType Directory -Force -Path ("{0}_{1} -f "$source, Get-Date)
You will still have to try and exclude this folder from the copy as well like Keith Hill's answer is telling you
Copy-Item $Source\* $BackupFolder -Exclude $BackupFolder
try Something like this
$Source = "C:\XYZ"
$Destination="{0}{1:yyyyMMdd}" -f $source, (Get-Date)
New-Item -ItemType Directory -Force -Path $Destination
Copy-Item -Path $Source\* $Destination -Recurse -Force
If I understand the question correctly. You want to take "C:\XYZ" and backup into the same directory called "C:\XYZ\backup_$DATE". What you will actually do is create a loop that will break once it reaches the max 248 characters. If we use the -exclude option then we can exclude the backup directory "C:\XYZ\backup_$DATE".
This function will do the trick and also gives you error handling.
Function Get-CopyDirectory{
#####################
# Dynamic Variables #
#####################
$Date = Get-Date -format ddMM-yyyy
$Exclude="Backup*"
####################
# Static Variables #
####################
$AppPath = "F:\Test\"
$BackupPath = "$AppPath\BACKUP_$Date\"
if (Test-Path $BackupPath) {
Write-Host "Backup Exist" -f Cyan
}
else
{
Copy-Item "$AppPath\*" $BackupPath -Exclude $Exclude -recurse -verbose
}
}
CLS
Get-CopyDirectory

Error message in script

I am trying to script a solution copying some files from one location to another..
I have a list of files in a .csv format, with headers
"ParentFolder, Name, FullName, lastwritetime."
Content of file is, which has hundreds of lines, and different paths, but same drive letter:
"X:\clients\A90\201AA3.05\","2012.08 RAP Proposal.xlsm","X:\clients\A90\201AA3.05\2012.08 RAP Proposal.xlsm","20/05/2016 10:41:08"
What i would like to do is copy the above..
"X:\clients\A90\201AA3.05\2012.08 RAP Proposal.xlsm" to a new location with differnet drive, but same directory structure. So in the csv file i have the filename and path, but am unsure how to split the drive from there and make a variable.
I have a foreach loop..
$ToCopy = Import-Csv "c:\temp\log.csv"
foreach($Line in $ToCopy)
{
$FullPath = $Line.ParentFolder
$File = $Line.Name
$FullName = $Line.FullName
$file = "$FullPath\$FullName"
$DestPath = Split-Path $FullPath -NoQualifier
Copy-Item "$FullName" -Destination c:\test\$DestPath
}
Error message that i am getting is :
+ CategoryInfo : NotSpecified: (:) [Copy-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : System.IO.DirectoryNotFoundException,Microsoft.PowerShell.Commands.CopyItemCommand
Copy-Item : Could not find a part of the path 'C:\test\clients\A90\Support\_index0901\'.
At line:9 char:9
+ Copy-Item "$FullName" -Destination c:\test\$DestPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], DirectoryNotFoundException
+ FullyQualifiedErrorId : System.IO.DirectoryNotFoundException,Microsoft.PowerShell.Commands.CopyItemCommand
You get the error because the directory structure of your target path probably does not exist
To solve that you can create a 'temporary' file with New-Item ... -Force which creates the missing directories if necessary and then overwrite that file with Copy-Item like so
$ToCopy = Import-Csv "c:\temp\log.csv"
foreach($Line in $ToCopy)
{
$FullPath = $Line.ParentFolder
$File = $Line.Name
$FullName = $Line.FullName
$file = "$FullPath\$FullName"
$DestPath = Split-Path $FullPath -NoQualifier
$DestFile = c:\test\$DestPath
New-Item -ItemType File -Force $DestFile
Copy-Item "$FullName" -Destination $DestFile -Force
}
You need to create the folders before attempting to copy files in them.
Here's a way to do it, simplified from what you have, but with an added line to take care of the folders' creation.
foreach($File in $ToCopy)
{
$DestPath = Join-Path -Path 'c:\test' -ChildPath ( Split-Path $File.ParentFolder -NoQualifier )
If ( -not ( Test-Path -Path $DestPath ) ) { New-Item -Path $DestPath -Force -ItemType Directory }
Copy-Item $File.FullName -Destination $DestPath -WhatIf
}
(Be careful, I change the iteration variable from $Line to $File)
You are trying to copy files into c:\test\ directory which does not exist. Create this directory before loop:
mkdir c:\test\
or, in case directory may exist
mkdir c:\test\ -Force