I have a Issue with Copy-Item in Powershell - powershell

My problem is that powershell always gives me the error msg :"cant overwrite file with itself" and i don't know why
$source=$textBox1.text
$dest=$textBox2.Text
$usr=$textBox3.text
#######From
$fNoBackup = "\\$source\c$\Users\$usr\AppData\Local\NoBackup\*"
$fData = "\\$source\c$\Users\$usr\AppData\Local\Lotus\Notes\Data\*"
$fCustomDestinations = "\\$source\c$\Users\$usr\AppData\Roaming\Microsoft\Windows\Recent\CustomDestinations\*"
$fAutomaticDestinations = "\\$source\c$\Users\$usr\AppData\Roaming\Microsoft\Windows\Recent\AutomaticDestinations\*"
#######To
$tNoBackup = "\\$dest\c$\Users\$usr\AppData\Local\NoBackup"
$tData = "\\$dest\c$\Users\$usr\AppData\Local\Lotus\Notes\Data"
$tCustomDestinations = "\\$dest\c$\Users\$usr\AppData\Roaming\Microsoft\Windows\Recent\CustomDestinations"
$tAutomaticDestinations = "\\$dest\c$\Users\$usr\AppData\Roaming\Microsoft\Windows\Recent\AutomaticDestinations"
#######le copy
#############"Touch" the files ;D
New-Item -ItemType File -Path $tNoBackup -Force
New-Item -ItemType File -Path $tData -Force
New-Item -ItemType File -Path $tCustomDestinations -Force
New-Item -ItemType File -Path $tAutomaticDestinations -Force
#############Copy
Copy-Item $fNoBackup $tNoBackup -Recurse -Force
Copy-Item $fData $tData -Recurse -Force
Copy-Item $fCustomDestinations $tCustomDestinations -Recurse -Force
Copy-Item $fAutomaticDestinations $tAutomaticDestinations -Recurse -Force

To debug this, I would recommend that you print out the contents of your variables to the console. That way, you will understand what the problem is.
I don't know Powershell, but I am seeing something which could be a problem. Obviously, $ within a string has a special meaning (it seems to denote variables). Therefore, I suspect that you have to quote (escape) the $ sign if you want it to be literal in the string.
In every of your strings, you have c$. That should probably be c`$ since ` is the escape character in Powershell. When you have done this, print the strings out to the console again to make sure you have got them right.

Related

Powershell Copy-Item not copying even when folder exists

I have two consecutive calls to Copy-Item but the second one is not copying the file. Both are copying the same file to two different folders. Both folders exist. But the second one never copies. I tried commenting out the first one, but the second one still does not copy.
$deliveryFolder = "C:\Users\administrator.GTCS\Desktop\Delivery\1.5.6.1140\"
$localFolder = "C:\WebServerGateway\"
$fileSharingServerManifestFileName = "GTCS_GCS_FileSharingServer_Manifest.xml"
Copy-item -Path $localFolder$fileSharingServerManifestFileName -Destination $deliveryFolder"GcsData\Configurations\Platforms\DEV\Web Server Gateway" -Force
Copy-item -Path $localFolder$fileSharingServerManifestFileName -Destination $deliveryFolder"GcsData\Configurations\Platforms\INT\Web Server Gateway" -Force
If you are going to combine strings in this manner you need to wrap them in double quotes, to expand the variables:
$deliveryFolder = "C:\Users\administrator.GTCS\Desktop\Delivery\1.5.6.1140\"
$localFolder = "C:\WebServerGateway\"
$fileSharingServerManifestFileName = "GTCS_GCS_FileSharingServer_Manifest.xml"
Copy-item -Path "$localFolder$fileSharingServerManifestFileName" -Destination "$($deliveryFolder)GcsData\Configurations\Platforms\DEV\Web Server Gateway" -Force
Copy-item -Path "$localFolder$fileSharingServerManifestFileName" -Destination "$($deliveryFolder)GcsData\Configurations\Platforms\INT\Web Server Gateway" -Force
Notice I uses a subexpression $() in the -Destination argument. Because in your case the parser may have trouble determining where the variable name ends, therefore the string may not expand properly.
That said, neither of the arguments are particularly pretty/readable so I'd advise against this syntax. concatenating or better yet using Join-Path to derive the arguments are better choices:
$Path = $localFolder + $fileSharingServerManifestFileName
$Dest = $deliveryFolder + "GcsData\Configurations\Platforms\INT\Web Server Gateway"
Note: Concatenation forces you to pay attention to backslashes separating what would be the -Parent/-Child arguments in Join-Path
Or:
$Path = Join-Path $localFolder $fileSharingServerManifestFileName
$Dest = Join-Path $deliveryFolder "GcsData\Configurations\Platforms\INT\Web Server Gateway"
Then simply modify the commands:
Copy-item -Path $Path -Destination $Dest -Force
Copy-item -Path $Path -Destination $Dest -Force

Powershell Variable for dynamic Move-Item

I have a function that looks at some registry settings for SQL Server which just pulls put the data and log location and puts them in variables. But I run into an issue when I pass them into Move-Item. Basically:
fnGetDataNLog
Returns $datalocation, $loglocation
When I run Move-Item -Path $datalocaton -Destination $loglocation I get
Cannot bind argument to parameter 'path' because it does not exist.
Is that due to its passing a runtime variable? Is there another way to do that then.
You can run a Test-Path to ensure the location exists.
If you $Datalocation is a UNC path to a directory you can do the below. eg. $Datalocation = '\\UNC\Path\To\Folder'
If(-not (Test-Path -Path $Datalocation)) {
New-Item -Path $Datalocation -ItemType Directory
}
Move-Item -Path $Datalocation-Destination $loglocation
This will test if the path at $Datalocation exists, if -not then it will create it.
if the UNC path is a string that goes to a file, ie. not an object result from a Get-ChildItem, then you can use a bit of regex to get the parent folder and then do the below. The regex will remove everything after the last \.
eg. \\UNC\Path\To\Folder\File.txt becomes \\UNC\Path\To\Folder\
If(-not (Test-Path -Path ($Datalocation -replace '[^\\]+$'))) {
New-Item -Path $Datalocation -ItemType Directory
}
Move-Item -Path $Datalocation -Destination $loglocation

powershell get-item | copy-item not keeping folder structure for just one folder

I am trying to move all folders/subfolders/subfiles from one folder on a server to another using a powershell script, while keeping the same file structure throughout. To do this I am using Get-childItem | copy-item. All folders, subfolders, and subfiles are moving properly EXCEPT for the first folder in the directory. It instead outputs all of these subfiles/subfolders from this folder into the destination. It does however keep their structure, just does not include their parent directory. My code is as follows:
Get-ChildItem $sourceFilePath -Force | Copy-Item -Destination ("*file path*" -f $destinationServer, $destinationClient) -Recurse -Force
filepath is paraphrased to improve readability
$sourceFilePath is the source folder that I am trying to copy
$destination server / $destinationClient are variables used in the paraphrased "file path"
I cannot figure out why this code works for all other folders, subfolders, and files EXCEPT for this one single folder and its items. Any help would be greatly appreciated, and if there's any other information that would help please let me know.
Answer thanks to #Christian Müller:
New-Item $destinationFilePath -name "MissingFolder" -type directory -Force | Out-Null
Get-ChildItem $sourceFilePath -Force | Copy-Item -Destination ("*filepath*" -f $destinationServer, $destinationClient) -Recurse -Force
This is a really strange bug and also astonished myself! :)
It seems when the destination base directory is not existing, than it is only created but not with content.
So with this construction, you can even debug this behaviour in ISE:
$sourceFilePath = "c:\temp\Test1"
$destPath = "c:\temp\Test2"
$a=Get-ChildItem $sourceFilePath -Force
rm -Force $destPath
foreach($x in $a) {
$x | Copy-Item -Destination "$destPath" -Recurse -Force
}
dir $destPath
Creating the target directory first, resolving the issue, with New-item:
$sourceFilePath = "c:\temp\Test1"
$destPath = "c:\temp\Test2"
$a=Get-ChildItem $sourceFilePath -Force
rm -Force $destPath
New-Item -ItemType Directory -Force -Path $destPath
foreach($x in $a) {
$x | Copy-Item -Destination "$destPath" -Recurse -Force
}
dir $destPath
But for my example it would work, to not using "Get-ChildItem" at all but
Copy-Item c:\temp\test1 -Destination c:\temp\test2 -Recurse -Force
Would this also work for you?
Copy-Item $sourceFilePath -Destination ("*file path*" -f $destinationServer, $destinationClient) -Recurse -Force

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

Powershell Remove-Item IF file already exists after Copy-item

I need to add a safety net in my script. I'm trying to do a copy job based on a list of users provided through a txt file. Copy the files from that users home directory to a new location. Once the files are copied, check if the file exists in the new location. If yes, then Remove-Item.
Can someone help me? I just don't know how to implement the "if file exists" logic.
$username = Get-Content '.\users.txt'
foreach ($un in $username)
{
$dest = "\\server\homedirs\$un\redirectedfolders"
$source = "\\server\homedirs\$un"
New-Item -ItemType Directory -Path $dest\documents, $dest\desktop
Get-ChildItem $source\documents -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\documents
Get-ChildItem $source\desktop -Recurse -Exclude '*.msg' | Copy-Item -Destination $dest\desktop
Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | Remove-Item -Recurse
}
The shortest way to delete file if it doesn't exist is NOT to use Test-Path but:
rm my_file.zip -ea ig
This is short version of
rm my_file.zip -ErrorAction Ignore
which is much more readable and more DRY then
if (Test-Path my_file.zip) { rm my_file.zip }
To answer your question per se, you can do it like this:
Get-ChildItem $source\mydocuments, $source\desktop -Recurse -Exclude '*.msg' | %{
if (Test-Path ($_. -replace "^$([regex]::escape($source))","$dest")) {
Remove-Item $_ -Recurse
}
}
Test-Path returns $true if the file at the given path exists, otherwise $false.
$_ -replace "^$([regex]::escape($source))","$dest" converts the path of each source item you're enumerating with the corresponding destination path, by replacing $source at the beginning of the path with $dest.
The basic regex for the first argument to the -replace operator is ^$source (which means "match the value of $source at the beginning of the string"). However, you need to use [regex]::escape in case $source contains any regex special characters, which is in fact extremely likely with Windows paths, since they contain backslashes. For example, the value you've given here for $source contains \s, which in a regex means "any whitespace character". $([regex]::escape($source)) will interpolate the value of $source with any regex special characters properly escaped, so that you're matching the explicit value.
That said, if your purpose is to copy each item to a new location, and remove the original only if the copy to the new location is successful, it seems like you're reinventing the wheel. Why not just use Move-Item instead of Copy-Item?
Not directly related to the question, but rather than repeating the same command for each subdirectory, you can use a foreach loop:
foreach ($subdir in (echo documents desktop)) {
# Whatever command you end up using to copy or move the items,
# using "$source\$subdir" and "$dest\$subdir" as the paths
}
Test-Path commandlet will help you check if the file exists
http://technet.microsoft.com/en-us/library/ee177015.aspx
#Adi Inbar, I need to use a function like this because I need to move files to a remote session, and the Move-Item does not work when I tried -ToSession... only Copy-Item.
The Key is that if the power or internet goes down, the script will delete the file even if it wasn't copied.
$username = "name"
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList ($username, $password)
$Session = New-PSSession -ComputerName "IPAdress" -Credential $credential
Copy-Item -Path C:\userPC_1\csv-output\*.csv -Destination C:\userPC_2\Documents\Test_Scripts -ToSession $Session -Verbose
Get-PSSession | Remove-PSSession
Get-ChildItem -Path C:\userPC_1\csv-output\*.csv | Remove-Item -Force