When trying to unzip files traditionally in Windows, it unzips to the name of the zip file as a folder with the files embedded into the folder itself. I am unable to recreate this using the Extract-Archive Cmdlet. Here is the code section for this that I have:
Get-ChildItem 'path of zip' -Filter *.zip | Expand-Archive -DestinationPath 'path to extract' -Force
While running this, the unzip process works fine. I am just wondering if there is a way to keep the traditional unzip file/folder structure when using the Expand-Archive Cmdlet
Thank you
You can set the destination folder in parameter DestinationPath. If the folder with the name of the zipfile does not yet exist, it will be created:
$sourcePath = 'path of zip file(s)'
$destination = 'path to extract'
Get-ChildItem -Path $sourcePath -Filter '*.zip' -File | ForEach-Object {
$target = Join-Path -Path $destination -ChildPath $_.BaseName
$_ | Expand-Archive -DestinationPath $target -Force
}
I have batch changed multiple files that all start with a prefix of a folder where I need them in.
The files are located on another location, like a folder on the desktop.
For example:
101AA0001.dat
101AA0002.dat
102AA0001.dat
102AA0002.dat
The destination folder will for example be:
C:\destfolder\101\ or C:\destfolder\102\
Files starting with 101 need to go in the 101 folder and the files starting with 102 go to folder 102.
I can find some scripts that creates the folder based on the filename. But in this situation the folders already exist. I also know for sure the files don't exist, so I don't have to overwrite files or something.
I guess it is easy for the people that know PowerShell very well, but I don't know how to do this. Can someone please help me? This can save me a lot of time.
I have tried to move the files with the following rule:
Move-Item -Path C:\Users\Username\Desktop\test*.dat -Destination C:\Users\Username\Desktop\test2\ -include "*.dat"
But it copies the whole folder except for the files.
You can do that quite easily with code like below:
$sourceFolder = Join-Path -Path $env:USERPROFILE -ChildPath 'Desktop'
$destination = 'C:\destfolder'
Get-ChildItem -Path $sourceFolder -File -Filter '*.dat' | ForEach-Object {
$targetFolder = Join-Path -Path $destination -ChildPath $_.Name.Substring(0, 3)
# if the target folder does not exist yet, create it
if (!(Test-Path -Path $targetFolder -PathType Container)) {
$null = New-Item -Path $targetFolder -ItemType Directory
}
$_ | Move-Item -Destination $targetFolder -WhatIf
}
The -WhatIf switch shows what would happen in the console without actually performing the move. If you are satisfied with what is output, remove that switch.
This will take all files that end in ".dat" from the $Source folder into a subfolder inside the $DestinationRoot named for the first three characters of the ".dat" file.
$Source = "C:\Users\Username\Desktop"
$DestinationRoot = "C:\Users\Username\Desktop\test2"
$Filelist = Get-ChildItem -Path $Source -Filter "*.dat" -File
foreach ($File in $Filelist){ $DestinationFolder = $File.Name.Substring(0,3)
$FinalPath = "$DestinationRoot\$DestinationFolder"
Move-Item -Path $File.Fullname -Destination $FinalPath -Whatif }
Remove the -Whatif when you're ready to run it for real.
This doesn't handle folder creation and should error out if the file already exists in the target location so it won't accidentally overwrite anything.
When destination folder exists the right way of copying files is defined here
Copy-Item 'C:\Source\*' 'C:\Destination' -Recurse -Force
If destination folder doesn't exist, some files in the source subfolders are copied straight into destination, without keeping original folder structure.
Is there a way to have a single Copy-Item command to address both cases and persist folder structure? Or is it too much to ask from Powershell?
You may want to use a if statement with test-path
this is the script i used to fix this problem
$ValidPath = Test-Path -Path c:\temp
If ($ValidPath -eq $False){
New-Item -Path "c:\temp" -ItemType directory
Copy-Item -Path "c:\temp" -Destination "c:\temp2" -force
}
Else {
Copy-Item -Path "c:\temp" -Destination "c:\temp2" -force
}
I am trying to copy a folder from the local computer to a remote server. It works but if the destination folder already exists it is creating a duplicate folder inside it.
copy-item -Path C:\test -Destination \\server\F$\testpassed -recurse -Force
To copy only the files from within C:\test to the \\server\F$\testpassed folder you need to use the following command:
Copy-Item -Path C:\test\* -Destination \\server\F$\testpassed -Recurse
\* is a wildcard for anything within the folder, and will cause Copy-Item to copy anything within the folder to the Destination. You could also use *.txt to only copy txt files if you wanted only a specific file type to be copied.
EDIT:
I would test for the presence of $TARGETDIR and then create it if needed. This way you only have a single copy command.
$TargetDir = "\\server\F$\testpassed"
$SourceDir = "C:\test"
if(!(Test-Path -Path $TARGETDIR)) {New-Item -Path $TARGETDIR -ItemType Directory}
Copy-Item -Path "$SourceDir\*" -Destination $TARGETDIR -Recurse
Using source path in below way will solve your issue
Copy-Item -Path C:\test*
Try
$Source = Get-childitem C:\test -Recurse
copy-item -Path $Source.FullName -Destination C:\temp -recurse -Force
Use GC to stop getting the folder as well as the contents.
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