What am I doing wrong with Copy-Item? - powershell

Copy-Item trips me up every time I use it. Would someone please tell me what I did wrong here?
I have a set of folders:
C:\FolderA\Thing\Sub1\1_file.css
C:\FolderA\Thing\Sub2\A_file.css
C:\FolderA\Thing\page.html
I try to use Copy-Item to send them to C:\FolderB\* and preserve structure:
Copy-Item -Path $srcFolder\Thing\* -Destination $destFolder\Thing -Recurse -Force -Verbose
Expected result:
C:\FolderB\Thing\Sub1\1_file.css
C:\FolderB\Thing\Sub2\A_file.css
C:\FolderB\Thing\page.html
Instead I end up with:
C:\FolderB\Sub1\1_file.css
C:\FolderB\Sub2\A_file.css
C:\FolderB\page.html
There's clearly a \Thing folder in there, so why doesn't it create the \Thing if I'm telling it to go recursively?

You need to tell it to create the directory before the copy, for example:
$dst = C:\FolderB\Thing
New-item $dst -type directory
`

Related

Powershell move all files and subfolders in a child folder to CURRENT directory

I tried this, no error but no files have modved :
Get-ChildItem -Path "subfolder\" -Recurse | Move-Item -Destination "."
Update: I don't want ABSOLUTE but RELATIVE path
Your answer will be something like:
Move-Item -Path 'subfolder\*' -Destination . -Force
This is relative and will process all hidden files en folders as well.
Set-Location 'C:\Users\username\Desktop\newFolder';
Get-ChildItem -Path 'C:\Users\username\Desktop\oldFolder\*.txt' -Recurse -File | Move-Item -Destination $(get-location).Path;
This may seem like a crazy attempt and to be honest the question isn't as comprehensive as I'd like. For example: I'm not sure if the folder will only every be 1 level deep or could be further down from the current directory. At any rate, I got something that seems to be working basically by not bothering with recursion:
$SubFolder = 'YourFolderName'
$SubFolder = Get-Item .\$SubFolder
Get-ChildItem $SubFolder |
ForEach-Object{
$Destination = $_.FullName -Replace "$($SubFolder.FullName.Replace('\','\\'))", ".\"
$NewParent = $Destination -Replace $_.Name
Move-Item $_.FullName -Destination $NewParent
}
I think the trick here is you have to move to the parent's parent, etc or however many levels back/up. So figure out what the new parent should be using the current directory syntax .\. Once you have that you can move everything from the first level over not using recursion. Move-Item on a folder it knows to move the whole thing, and the files that are found in Sub-folder itself will obviously move to the new correct parent.
I had another working version that did use recursion, but this seems more concise and much to my surprise this seems to work. However, I'm not thrilled with it.

Check if file exists, then move it

I'm trying to write a few lines of code in powershell, to check if a file arrived to a specific folder. If the file is there, copy it to another folder. No action required if the file is not there. So far I have only the copying part:
cd C:\
Move /y "C:\myfolder\*.csv" "C:\MyDestinationFolder"
I can't find a simple code to check if the file is present.
Maybe you can use this:
$SourceFile = "C:\source\file.txt"
$Destination = "C:\destination\"
if(Test-Path -Path $SourceFile)
{
Copy-Item -Path $SourceFile -Destination $Destination
}
try this :
move-Item "C:\myfolder\*.csv" "C:\MyDestinationFolder" -Force -ErrorAction SilentlyContinue

how to move bulk move files and then rename them in sequential order?

to test, I'm trying to move c:\Users\myuser\Downloads\test.txt to c:\Users\myuser\Documents\mynewname0001.txt.
The destination folder path is dynamic so for my test I'm using a variable
My final aim is to use GCI + ForEach-Object to move lots and lots of files. But I'm testing with a single file for now.
Here's my script:
$_test = "c:\Users\myuser\Documents"
$_i = 1
Move-Item -Path "$($_test)\test.txt" -Destination "($($_test)\temp\'newname{0:D4}' -f $_i++)"
This is the error I'm getting
Move-Item : Cannot find drive. A drive with the name '(c' does not exist.
I can move the files if I don't order them using:
Move-Item -Path "$($_test)\test.txt" -Destination "$($_test)\temp\newname.txt"
But I do not know how to introduce the auto incrementing code with it.
Can you please help? Thanks
Try to evaluate the format string separately:
Move-Item -Path "$($_test)\test.txt" -Destination "$_test\a\$('newname{0:D4}' -f $_i++)"

Why is PowerShell copying to a random location?

I have the following simple script:
$workingDir = "C:\foo\bar"
$projectsDir = "C:\foo"
Copy-Item -Path "$projectsDir\some subpath\MyFile1.dll" -Destination $workingDir
Copy-Item -Path "$projectsDir\somewhere else\MyFile2.dll" -Destination $workingDir
Copy-Item -Path "$projectsDir\another place\MyFile3.dll" -Destination $workingDir
For some unknown reason, every time I run this script it copies the files to the correct location ($workingDir) and also copies them to $projectsDir\some subpath\something\else. I have to go delete the extra files from the other location every time this script is run.
So far I've tried:
changing variable names
specifying -Destination "$workingDir\MyFile1.dll"
using $null = Copy-Item -Path "...."
I even tried replacing Copy-Item with xcopy.exe
and nothing changes. I put a breakpoint on the first Copy-Item command and looked at the variables - they all looked right. What's going on here?
The only other thing I could think of is to run the copy-item like this:
Copy-Item -Path $($projectsDir + "\some subpath\MyFile1.dll") -Destination $workingDir
This is how I declare almost all of my Variable + SomethingElse scenarios. Since I haven't scene this behavior, I'll go back and test it some more to see what I can find. If I come up with something else, I redo my answer.
I rebooted my computer. Problem solved.

Should Copy-Item create the destination directory structure?

I'm trying to copy a file to a new location, maintaining directory structure.
$source = "c:\some\path\to\a\file.txt"
destination = "c:\a\more\different\path\to\the\file.txt"
Copy-Item $source $destination -Force -Recurse
But I get a DirectoryNotFoundException:
Copy-Item : Could not find a part of the path 'c:\a\more\different\path\to\the\file.txt'
The -recurse option only creates a destination folder structure if the source is a directory. When the source is a file, Copy-Item expects the destination to be a file or directory that already exists. Here are a couple ways you can work around that.
Option 1: Copy directories instead of files
$source = "c:\some\path\to\a\dir"; $destination = "c:\a\different\dir"
# No -force is required here, -recurse alone will do
Copy-Item $source $destination -Recurse
Option 2: 'Touch' the file first and then overwrite it
$source = "c:\some\path\to\a\file.txt"; $destination = "c:\a\different\file.txt"
# Create the folder structure and empty destination file, similar to
# the Unix 'touch' command
New-Item -ItemType File -Path $destination -Force
Copy-Item $source $destination -Force
Alternatively, with PS3.0 onwards, you can simply use the New-Item to create the target folder directly, without having to create a "dummy" file, e.g. ...
New-Item -Type dir \\target\1\2\3\4\5
...will happily create the \\target\1\2\3\4\5 structure irrespective of how much of it already exists.
Here's a oneliner to do this. Split-Path retrieves the parent folder, New-Item creates it and then Copy-Item copies the file. Please note that the destination file will have the same filename as the source file. Also, this won't work if you need to copy multiple files to the same folder as with the second file you'll get An item with the specified name <destination direcory name> already exists error.
Copy-Item $source -Destination (New-Item -Path (Split-Path -Path $destination) -Type Directory)
I had files in a single folder in Windows 7 that I wanted to rename and copy to nonexistent folders.
I used the following PowerShell script, which defines a Copy-New-Item function as a wrapper for the Test-Item, New-Item, and Copy-Item cmdlets:
function Copy-New-Item {
$SourceFilePath = $args[0]
$DestinationFilePath = $args[1]
If (-not (Test-Path $DestinationFilePath)) {
New-Item -ItemType File -Path $DestinationFilePath -Force
}
Copy-Item -Path $SourceFilePath -Destination $DestinationFilePath
}
Copy-New-Item schema_mml3_mathml3_rnc schema\mml3\mathml3.rnc
# More of the same...
Copy-New-Item schema_svg11_svg_animation_rnc schema\svg11\svg-animation.rnc
# More of the same...
Copy-New-Item schema_html5_assertions_sch schema\html5\assertions.sch
# More of the same...
(Note that, in this case, the source file names have no file extension.)
If the destination file path does not exist, the function creates an empty file in that path, forcing the creation of any nonexistent directories in the file path. (If Copy-Item can do all that by itself, I could not see how to do it from the documentation.)
It is coming late, but as I stumbled upon this question looking for a solution to a similar problem, the cleanest one I found elsewhere is using robocopy instead of Copy-Item. I needed to copy the whole file structure together with the files, that's easily achieved via
robocopy "sourcefolder" "destinationfolder" "file.txt" /s
Detail about robocopy: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy
None of the current answers worked for me to fix the Could not find a part of the path error raised by Copy-Item. After some research and testing, I discovered this error can be raised if the Destination path goes over the 260 character Windows path length limit.
What I mean by that is: if you supply a path to the Destination argument of Copy-Item and any of the files you are copying would exceed the 260 character limit when copied to the Destination folder, Copy-Item will raise the Could not find a part of the path error.
The fix is to shorten your Destination path, or to shorten/flatten the folder structure in the source directory that you are trying to copy.
May be Helpfull:
$source = 'c:\some\path\to\a\file.txt'
$dest = 'c:\a\more\different\path\to\the\file.txt'
$dest_dir = 'c:\a\more\different\path\to\the\'
[System.IO.Directory]::CreateDirectory($dest_dir);
if(-not [System.IO.File]::Exists($dest))
{
[System.IO.File]::Copy($source,$dest);
}
I have been digging around and found a lot of solutions to this issue, all being some alteration not just a straight copy-item command. Grant it some of these questions predate PS 3.0 so the answers are not wrong but using powershell 3.0 I was finally able to accomplish this using the -Container switch for copy-item.
Copy-Item $from $to -Recurse -Container
this was the test i ran, no errors and destination folder represented the same folder structure.
New-Item -ItemType dir -Name test_copy
New-Item -ItemType dir -Name test_copy\folder1
New-Item -ItemType file -Name test_copy\folder1\test.txt
#NOTE: with no \ at the end of the destination the file is created in the root of the destination, does not create the folder1 container
#Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2 -Recurse -Container
#if the destination does not exists this created the matching folder structure and file with no errors
Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2\ -Recurse -Container