首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Powershell复制文件夹并排除根级别的一个文件。

Powershell复制文件夹并排除根级别的一个文件。
EN

Stack Overflow用户
提问于 2022-11-10 02:08:55
回答 1查看 33关注 0票数 1

假设我有以下文件夹结构:

代码语言:javascript
运行
复制
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仍应复制。

我试过这个命令:

代码语言:javascript
运行
复制
Copy-Item -Path "C:\Source\" -Exclude "C:\Destination\file1.txt" -Recurse -Force

但是Exclude参数显然不接受绝对路径。如果我就这么做

代码语言:javascript
运行
复制
Copy-Item -Path "C:\Source\" -Exclude "file1.txt" -Recurse -Force

然后,C:\Source\more\file1.txt中的文件也将被排除在外。但是应该复制这个文件,只有位于Source文件夹中的Source应该被跳过。

EN

回答 1

Stack Overflow用户

发布于 2022-11-10 04:37:08

此函数可以执行与Copy-Item相同的操作,但可以根据作为参数传递给-ExcludeExpression的表达式排除文件和文件夹。表达式以Script Block的形式传递,可以接受多个筛选表达式。我不会详细讨论这些代码,因为它相当复杂。

代码语言:javascript
运行
复制
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.结束的绝对路径的任何文件或文件夹

代码语言:javascript
运行
复制
Copy-Stuff .\source\* -Destination .\destination -ExcludeExpression {
    $_.FullName.EndsWith('\Source\file1.txt')
} -Recurse
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74383406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档