Powershell 将文件从源复制到目标但保持文件夹结构
Powershell copy a file from source to target but maintain folder structure
我怎样才能想出一个可以将文件从位置 A 复制到位置 B 并创建新文件夹并维护子目录结构的 powershell 脚本
伪代码
$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
此代码未创建文件夹结构,我希望创建文件夹结构用户此参数 $maintainFolderStructureFrom ="Website"
首先,您应该使用 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
这里有一些想法:
New-Item
cmdlet 可以创建文件和文件夹,包括必要的父文件夹(如果它们不存在)。使用 -Force
开关。更重要的是,它将 return 一个 [System.IO.DirectoryInfo]
类型的对象供您使用。
- 如果将
$pathToCopy
变量设为 [System.IO.FileInfo]
对象,您将获得一些有用的属性和方法,这些属性和方法与使用 Get-Item
cmdlet 后可能习惯的其他文件相同.
Resolve-Path
cmdlet 可用于为您的路径提供一致的格式(例如“\”而不是“/”等),但请注意它需要解析为实际存在的内容。请记住提取该 cmdlet 为您提供的 Path 属性。
- 有一个很酷的 "Escape" 方法与
[Regex]
class 相关联,可以帮助剥离部分文件路径。
下面展示了一些您可能想要或可能不想使用的东西:
$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
这绝对是一种比您可能想要使用的更长的方法,但我希望该示例包含一些您可以尝试的想法。
类似问题的备选答案:
- 您可以尝试使用
RoboCopy
,根据对此处类似问题的回答:
What's the proper way to copy files while preserving folder structure in powershell?
或在这里查看答案:
Copying files while preserving directory structure
我喜欢其中一些答案,但觉得它们过于冗长,所以我将针对同一问题提供一个较短的答案。
这里的流程是递归抓取源码目录为$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
}
在@jisaak 和@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\'
我怎样才能想出一个可以将文件从位置 A 复制到位置 B 并创建新文件夹并维护子目录结构的 powershell 脚本
伪代码
$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
此代码未创建文件夹结构,我希望创建文件夹结构用户此参数 $maintainFolderStructureFrom ="Website"
首先,您应该使用 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
这里有一些想法:
New-Item
cmdlet 可以创建文件和文件夹,包括必要的父文件夹(如果它们不存在)。使用-Force
开关。更重要的是,它将 return 一个[System.IO.DirectoryInfo]
类型的对象供您使用。- 如果将
$pathToCopy
变量设为[System.IO.FileInfo]
对象,您将获得一些有用的属性和方法,这些属性和方法与使用Get-Item
cmdlet 后可能习惯的其他文件相同. Resolve-Path
cmdlet 可用于为您的路径提供一致的格式(例如“\”而不是“/”等),但请注意它需要解析为实际存在的内容。请记住提取该 cmdlet 为您提供的 Path 属性。- 有一个很酷的 "Escape" 方法与
[Regex]
class 相关联,可以帮助剥离部分文件路径。
下面展示了一些您可能想要或可能不想使用的东西:
$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
这绝对是一种比您可能想要使用的更长的方法,但我希望该示例包含一些您可以尝试的想法。
类似问题的备选答案:
- 您可以尝试使用
RoboCopy
,根据对此处类似问题的回答:
What's the proper way to copy files while preserving folder structure in powershell?
或在这里查看答案:
Copying files while preserving directory structure
我喜欢其中一些答案,但觉得它们过于冗长,所以我将针对同一问题提供一个较短的答案。
这里的流程是递归抓取源码目录为$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
}
在@jisaak 和@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\'