Copy a single file to a non-existing folder - powershell

It's easy to copy multiple files to a folder that doesn't exists and let it be created:
Copy-Item C:\Temp\aa C:\Temp2\DoesNotExist
The command above will create the folder DoesNotExist. That's what I'm after.
But what is the PowerShell syntax to the same when the source is only a single file?
Copy-Item C:\Temp\test.txt C:\Temp2\DoesNotExist
I tried C:\Temp2\DoesNotExist\ (with the trailing slash), but Powershell says "The filename, directory name, or volume label syntax is incorrect." and refuses to copy the single file.

If you're looking for a one liner solution, you can do this.
copy "C:\test2.txt" -Destination (New-Item "C:\Temp2\DoesNotExist\" -Type container -force) -Container -force

I think Geoff Guynn's one-liner should be as follows:
Copy-Item -Path "C:\test2.txt" -Destination (New-Item "C:\Temp2\DoesNotExist\" -ItemType directory -Force) -Force
The parameter for the cmdlet New-Item should be -ItemType and the intended "Type" should be directory.
The additional parameter -Container for the cmdlet Copy-Item seems to me superfluous; on the one hand it is set to $true by default anyway, on the other hand a single file should be copied and not the folder structure should be preserved.

Related

powershell avoid error message copy-item for an existing folder

I tried with -force but I still get error message
Copy-Item : An item with the specified name C:\folder2 already
exists.
Copy-Item 'c:\folder1' -Destination 'c:\folder2' -force
You can create the destination folder first and then copy everything inside the source folder by adding \* to the path:
# first create the destination folder if it does not already exist
$null = New-Item -Path 'c:\folder2' -ItemType Directory -Force
# then copy all from the source folder to the destination
Copy-Item -Path 'c:\folder1\*' -Destination 'c:\folder2' -Recurse -Force
By using switch -Force on the New-Item command, the cmdlet returns either the object of a newly created folder or the object of an existing folder.
In both cases, we do not need that output, so we'll ignore it using $null =

PowerShell Copy-Item not creating subfolders

I want Copy-Item to copy to the destination file and create any subfolders on the way, but I can't seem to get that to work.
Copy-Item $fullsrc $fulldst -Recurse -Force -Verbose
$fullsrc and $fulldst are full paths with filenames as the destination filename is different from the source filename. Is there a way to get Copy-Item to create the subfolders and then copy the file over?
VERBOSE: Performing the operation "Copy File" on target "Item: D:\mypath\logs\001.123.log
Destination: D:\newpath\newlogs\123.234.log".
Copy-Item : Could not find a part of the path 'D:\newpath\newlogs\123.234.log'.
Copy-item have't function to create a folder, you need to previously create it
Copy-Item $fullsrc $(new-item -ItemType Directory -Path $fulldst) -Recurse -Force -Verbose -ErrorAction SilentlyContinue
You have to create the parent directory of the destination file on your own.
# Split-Path with single parameter outputs the parent directory
$null = New-Item (Split-Path $fulldst) -ItemType Directory
Copy-Item $fullsrc $fulldst -Force -Verbose
Note that -Recurse switch has no use when you specify full source and destination file paths, so I've removed it.

Compress-Archive Error: Cannot access the file because it is being used by another process

I would like to zip a path (with a service windows running inside).
When the service is stopped, it works perfectly, when the service is running, I have the exception:
The process cannot access the file because it is being used by another
process.
However, when I zip with 7-zip, I don't have any exception.
My command:
Compress-Archive [PATH] -CompressionLevel Optimal -DestinationPath("[DEST_PATH]") -Force
Do you have any idea to perform the task without this exception?
Copy-Item allows you to access files that are being used in another process.
This is the solution I ended up using in my code:
Copy-Item -Path "C:\Temp\somefolder" -Force -PassThru |
Get-ChildItem |
Compress-Archive -DestinationPath "C:\Temp\somefolder.zip"
The idea is that you pass through all the copied items through the pipeline instead of having to copy them to a specific destination first before compressing.
I like to zip up a folder's content rather than the folder itself, therefore I'm using Get-ChildItem before compressing in the last line.
Sub-folders are already included. No need to use -recurse in the first line to do this
A good method to access files being used by another process is by creating snapshots using Volume Shadow Copy Service.
To do so, one can simply use PowerShells WMI Cmdlets:
$Path = "C:/my/used/folder"
$directoryRoot = [System.IO.Directory]::GetDirectoryRoot($Path).ToString()
$shadow = (Get-WmiObject -List Win32_ShadowCopy).Create($directoryRoot, "ClientAccessible")
$shadowCopy = Get-WmiObject Win32_ShadowCopy | ? { $_.ID -eq $shadow.ShadowID }
$snapshotPath = $shadowCopy.DeviceObject + "\" + $Path.Replace($directoryRoot, "")
Now you can use the $snapshotPath as -Path for your Compress-Archive call.
This method can also be used to create backups with symlinks.
From there on you can use the linked folders to copy backed up files, or to compress them without those Access exceptions.
I created a similiar function and a small Cmdlet in this Gist: Backup.ps1
There was a similar requirement where only few extensions needs to be added to zip.
With this approach, we can copy the all files including locked ones to a temp location > Zip the files and then delete the logs
This is bit lengthy process but made my day!
$filedate = Get-Date -Format yyyyMddhhmmss
$zipfile = 'C:\Logs\logfiles'+ $filedate +'.zip'
New-Item -Path "c:\" -Name "Logs" -ItemType "directory" -ErrorAction SilentlyContinue
Robocopy "<Log Location>" "C:\CRLogs\" *.txt *.csv *.log /s
Get-ChildItem -Path "C:\Logs\" -Recurse | Compress-Archive -DestinationPath $zipfile -Force -ErrorAction Continue
Remove-Item -Path "C:\Logs\" -Exclude *.zip -Recurse -Force

Move-Item not moving top folder in some cases

Trying to move all files and folders and how its behaving has me a little stumped.
Let's say we have a folder tree like Below
Example Path
Folder A
FileA1
FileA2
Folder B
FileB1
When using the Move-Item command like this move-Item -Path 'C:\Example Path\*' -Destination 'C:\Destination Path' every time the first folder in the list just seems to get deleted. So the outcome of that command would be like this.
Destination Path
FileA1
FileA2
Folder B
FileB1
How would I get around this issue, Or am I doing something incorrectly here? Any help would be gladly appreciated.
i try this on my pc, it's working (PowerShell v5)
move-item -Path "C:\temp\Example Path" -Destination "C:\temp\Destination Path"
Try creating the destination folder manually before running the Move-Item command.
New-Item -ItemType directory -Path 'C:\Destination Path'
Move-Item -Path 'C:\Example Path\*' -Destination 'C:\Destination Path'
https://github.com/PowerShell/PowerShell/issues/13352#issuecomment-669025179

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