Powershell将文件从源复制到目标但保留文件夹结构

时间:2016-01-22 08:56:22

标签: powershell copy

如何创建一个powershell脚本,可以将文件从位置A复制到位置B并创建新文件夹并维护子目录结构

伪代码

$newFolder = "PackageName"
$maintainFolderStructureFrom ="Website"
$FileToCopy = "File.ascx"

Copy-Item "C:\A\B\Website\SubFolder1\SubFolder2\SubFolder3\"+$FileToCopy "C:\Client\Packages\$newFolder" -Container -Recurse

现在它应该创建目标

C:\Client\Packages\PackageName\SubFolder1\SubFolder2\SubFolder3\File.ascx

基于@jisaak回答的代码

$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  

这段代码不是创建文件夹结构,我希望用户创建文件夹结构这个param $ maintainFolderStructureFrom ="网站"

5 个答案:

答案 0 :(得分:1)

首先,您应该使用Join-Path cmdlet来组合路径。您可以使用mkdir创建目录(如果目录已存在,请使用-ErrorAction SilentlyContinue忽略错误):

$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

答案 1 :(得分:1)

这里有一些想法:

  • New-Item cmdlet可以创建文件和文件夹,包括必要的父文件夹(如果它们不存在)。使用-Force开关。更重要的是,它将返回一个[System.IO.DirectoryInfo]类型的对象供您使用。
  • 如果您将$pathToCopy变量设为[System.IO.FileInfo]对象,则会获得一些与使用Get-Item cmdlet后可能习惯使用的其他文件相同的有用属性和方法。< / LI>
  • Resolve-Path cmdlet可用于为路径提供一致的格式(例如'\'而不是'/'等),但请注意,它需要解析为实际存在的内容。请记住提取该cmdlet为您提供的路径属性。
  • 有一个很酷的“Escape”方法与[Regex]类相关联,可以帮助剥离部分文件路径。

以下展示了您可能想要或不想使用的一些内容:

$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

这绝对是一个比你可能想要使用的更长的方法,但我希望这个例子包含你可以尝试的一些想法。

答案 2 :(得分:0)

类似问题的替代答案:

  • 您可以尝试使用RoboCopy,根据类似问题的答案:
  

What's the proper way to copy files while preserving folder structure in powershell?

或者看看这里的答案:

  

Copying files while preserving directory structure

答案 3 :(得分:0)

我喜欢一些答案,但觉得他们过于冗长,所以我会对同样的事情提出更短的看法。

此处的流程是以$source递归方式获取源目录。接下来,遍历它,拉出所有目录,并为每个目录,在目标中创建一个新文件夹。

最后,最后一次返回$source以获取此次文件,并将它们放在新位置。

$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
    }

答案 4 :(得分:0)

从@jisaak&amp;中获得一些答案的帮助@FoxDeploy,我可以完成我的需要。

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)
}
}

然后将其称为

CreatePackage -packageName 'MyNewPackage' -fileSelectorToCopy 'FileNameLike.*' -sourcePath 'C:\A\B\Website\SubFolder1\SubFolder2\SubFolder3\'