How can I come up with a powershell script that can copy a file from a location A to location B and create new folder and maintain the sub directory structure
Pseudo code
$newFolder = "PackageName"
$maintainFolderStructureFrom ="Website"
$FileToCopy = "File.ascx"
Copy-Item "C:\A\B\Website\SubFolder1\SubFolder2\SubFolder3\"+$FileToCopy "C:\Client\Packages\$newFolder" -Container -Recurse
Now it should create the target as such
C:\Client\Packages\PackageName\SubFolder1\SubFolder2\SubFolder3\File.ascx
Code based on @jisaak answer
$newFolder = "NewFolderName"
$FileToCopy="File.ascx"
$pathToCopy = Join-Path 'C:\A\B\Website\SubFolder1\SubFolder2\SubFolder3\' $FileToCopy
$destination = Join-Path 'C:\Client\Packages\' $newFolder
mkdir $destination -ErrorAction SilentlyContinue
Copy-Item $pathToCopy $destination
This code is not creating folder structure, I want the folder structure to be created user this param $maintainFolderStructureFrom ="Website"
First, you should use the Join-Path cmdlet to combine paths. You could create the directories using mkdir
(use -ErrorAction SilentlyContinue
to ignore errors if the directory already exists):
$pathToCopy = Join-Path 'C:\A\B\Website\SubFolder1\SubFolder2\SubFolder3' $FileToCopy
$destination = Join-Path 'C:\Client\Packages' $newFolder
# create the directory if necessary
mkdir $destination -ErrorAction SilentlyContinue
Copy-Item $pathToCopy $destination
A few ideas here:
New-Item
cmdlet can create files and folders, including the necessary parent folder if they don't exist. Use the -Force
switch. What's more, it will return a [System.IO.DirectoryInfo]
type object for you to work with. $pathToCopy
variable a [System.IO.FileInfo]
object you get a few useful properties and methods in common with other files that you may be used to after using the Get-Item
cmdlet. Resolve-Path
cmdlet can be useful to give a consistent format for your paths (eg '\\' rather than '/', etc.) but note that it needs to resolve to something that actually exists. Remember to pull out the Path property of what that cmdlet gives you. [Regex]
class that can help stripping off parts of a file path. The following shows off some of these things that you may or may not want to use:
$SourceRoot = "C:\A\B\Website"
$SourcePath = "\SubFolder1\SubFolder2\SubFolder3"
$SourceFile = "File.ascx"
$DestRoot = "C:\Client\Packages"
$NewFolder = "PackageName"
# Build a full path to your source file
$FileToCopy = Join-Path -Path $SourceRoot -ChildPath $SourcePath
$FileToCopy = Join-Path -Path $FileToCopy -ChildPath $SourceFile
# Make this a FileInfo object, just because we can :-)
$FileToCopy = $FileToCopy -as [System.IO.FileInfo]
# Or you could have used Get-ChildItem instead:
$FileToCopy = Resolve-Path ($SourceRoot+$SourcePath+$SourceFile)
$FileToCopy = Get-ChildItem -Path $FileToCopy.Path
# Strip off the "root" folders so we're just left with the relative
# path to the source file from the source root folder
$RelativePath = $FileToCopy.Directory -replace [Regex]::Escape($SourceRoot),''
# Join up the destination path components
$DestFolder = Join-Path $DestRoot $NewFolder
$DestFolder = Join-Path $DestFolder $RelativePath
# Create the target folder if necessary & convert the $DestFolder
# variable into a [System.IO.DirectoryInfo] object!
$DestFolder = New-Item -ItemType Directory -Path $DestFolder -Force
# Copy the file
Copy-Item $FileToCopy $DestFolder
This is definitely a longer way to do this than you'll probably want to use, but I wanted the example to include a number of the ideas you could try.
Alternative answers to similar questions:
RoboCopy
, as per an answer to a similar question here: What's the proper way to copy files while preserving folder structure in powershell?
Or look at the answer here:
I like some of the answers, but feel that they're overly verbose, so I'll offer a shorter take on the same thing.
The flow here is to recursively grab the source directory as $source
. Next, iterate through it, pulling out all the directories, and for each of those, make a new folder in the target.
Finally, go back through $source
one last time to get the files this time, and put them in the new location.
$source = DIR -Path C:\SomeOldPath -Recurse
$destination = 'C:\SomeNewPath'
$source | Where PSIsContainer | ForEach-Object {
#If the folder doesn't exist in the target
if(!(Test-Path $Destination\$_.Name -PathType Container)){
New-Item -Path $Destination\$_.Name -ItemType directory -Force}
}
else {
Copy-Item $_.FullName -Destination $Destination\$_.Name -Force}
$source | Where PSIsContainer -eq $false | ForEach-Object {
Copy-Item $_.FullName -Destination $Destination\$_.Name -Force
}
taking help of few answers from @jisaak & @FoxDeploy, I could accomplish what I need.
function CreatePackage($sourcePath, $fileSelectorToCopy, $packageName) {
$maintainStructionFrom = "Website"
$files = Get-ChildItem $sourcePath | Where-Object {$_.Name -match $fileSelectorToCopy}
$files | ForEach-Object {
$newFolder = $packageName
$fileSelectorToCopy = $_.Name
$pathToCopy = Join-Path $sourcePath $fileSelectorToCopy
$newFolder = $newFolder+'\'+$pathToCopy.Substring($pathToCopy.IndexOf($maintainStructionFrom),$pathToCopy.Length - $pathToCopy.IndexOf($maintainStructionFrom)).Replace($fileSelectorToCopy,'')
$destination = Join-Path 'C:\Client\Packages\' $newFolder
mkdir $destination -ErrorAction SilentlyContinue
Copy-Item $pathToCopy ($destination+$FileToCopy)
}
}
Then call it as
CreatePackage -packageName 'MyNewPackage' -fileSelectorToCopy 'FileNameLike.*' -sourcePath 'C:\A\B\Website\SubFolder1\SubFolder2\SubFolder3\'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.