假设我有以下文件夹结构:
C:\Source\file1.txt
C:\Source\file2.txt
C:\Source\file3.txt
C:\Source\more\file1.txt
C:\Source\more\file4.txt
C:\Destination\file1.txt
C:\Destination\file2.txt
C:\Destination\file3.txt
C:\Destination\more\file1.txt
C:\Destination\more\file4.txt
我试图编写一个PowerShell脚本,它将源文件夹中的所有内容复制到目标文件夹,但文件C:\Source\file1.txt
除外。文件C:\Source\more\file1.txt
仍应复制。
我试过这个命令:
Copy-Item -Path "C:\Source\" -Exclude "C:\Destination\file1.txt" -Recurse -Force
但是Exclude
参数显然不接受绝对路径。如果我就这么做
Copy-Item -Path "C:\Source\" -Exclude "file1.txt" -Recurse -Force
然后,C:\Source\more\file1.txt
中的文件也将被排除在外。但是应该复制这个文件,只有位于Source
文件夹中的Source
应该被跳过。
发布于 2022-11-10 04:37:08
此函数可以执行与Copy-Item
相同的操作,但可以根据作为参数传递给-ExcludeExpression
的表达式排除文件和文件夹。表达式以Script Block
的形式传递,可以接受多个筛选表达式。我不会详细讨论这些代码,因为它相当复杂。
function Copy-Stuff {
param(
[Parameter(ParameterSetName = 'Path', Mandatory, Position = 0, ValueFromPipeline)]
[string[]] $Path,
[Parameter(ParameterSetName = 'LiteralPath', Mandatory, ValueFromPipelineByPropertyName)]
[Alias('PSPath')]
[string[]] $LiteralPath,
[Parameter(Mandatory, Position = 1)]
[string] $Destination,
[Parameter()]
[scriptblock[]] $ExcludeExpression,
[Parameter()]
[switch] $Recurse,
[Parameter()]
[switch] $Force,
[Parameter()]
[string] $Filter = '*'
)
begin {
$stack = [Collections.Generic.Stack[IO.FileSystemInfo]]::new()
$Destination = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($Destination)
}
process {
$isLiteral = $PSBoundParameters.ContainsKey('LiteralPath')
$paths = $Path
if($isLiteral) {
$paths = $LiteralPath
}
foreach($item in $ExecutionContext.InvokeProvider.Item.Get($paths, $true, $isLiteral)) {
if($item.FullName -eq $Destination) {
continue
}
$stack.Push($item)
$here = $item.Parent.FullName
if($item -is [IO.FileInfo]) {
$here = $item.Directory.FullName
}
:outer while($stack.Count) {
$item = $stack.Pop()
foreach($expression in $ExcludeExpression) {
if($expression.InvokeWithContext($null, [psvariable]::new('_', $item))) {
continue outer
}
}
$to = Join-Path $Destination -ChildPath $item.FullName.Replace($here, '')
if($item -is [IO.DirectoryInfo]) {
$null = [IO.Directory]::CreateDirectory($to)
if($Recurse.IsPresent) {
try {
$enum = $item.EnumerateFileSystemInfos($Filter)
}
catch {
$PSCmdlet.WriteError($_)
continue
}
}
foreach($child in $enum) {
$stack.Push($child)
}
continue
}
try {
$null = $item.CopyTo($to, $Force.IsPresent)
}
catch {
if($_.Exception.InnerException -is [IO.DirectoryNotFoundException]) {
$null = [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($to))
continue
}
$PSCmdlet.ThrowTerminatingError($_)
}
}
}
}
}
你该怎么用呢?
源后面的星号*
表示要复制 source
中的所有文件和文件夹,而不是复制source
本身。
应该相应地更改表达式{ $_.FullName.EndsWith('\Source\file1.txt') }
,并且可以添加多个表达式。在这种情况下,它将排除以\Source\file1.txt
.结束的绝对路径的任何文件或文件夹
Copy-Stuff .\source\* -Destination .\destination -ExcludeExpression {
$_.FullName.EndsWith('\Source\file1.txt')
} -Recurse
https://stackoverflow.com/questions/74383406
复制相似问题