【问题标题】:Copy-Item without source directory没有源目录的复制项
【发布时间】:2018-06-13 13:46:15
【问题描述】:

我正在尝试为一个简单的备份系统镜像几个文件夹。

假设我有以下文件结构:

c:\temp\a.txt
c:\temp\b.txt
c:\temp\sub\a.txt
c:\temp\sub\112233.txt
c:\temp\sub2\pictureofaduck.jpg

我的目标是将c:\temp\ 的全部内容复制到一个新的目的地(D:\mybackup\),如下所示:

d:\mybackup\a.txt
d:\mybackup\b.txt
d:\mybackup\sub\a.txt
d:\mybackup\sub\112233.txt
d:\mybackup\sub2\pictureofaduck.jpg

我错误地认为这对于使用此行的 Copy-Item 来说应该是一件容易的事:

Copy-Item 'C:\temp\' -Destination 'D:\mybackup\' -Recurse

出乎我的意料,Copy-Item 非常渴望在游戏中保留那个“临时”文件夹。因为无论我尝试什么通配符和 - 在结尾组合,我要么得到以下结果,要么只复制两个文件 a.txt 和 b.txt。

d:\mybackup\temp\a.txt
d:\mybackup\temp\b.txt
d:\mybackup\temp\sub\123.txt
d:\mybackup\temp\sub\112233.txt
d:\mybackup\temp\sub2\pictureofaduck.jpg

请帮帮我,这太荒谬了。

PS:这个问题的解决方案在这里不起作用 - 去过那里。我只得到根文件:

Copy entire folder structure in Powershell without re-creating root folder

【问题讨论】:

  • 这有帮助吗? Copy-Item 'C:\temp\*' -Destination 'D:\mybackup\' -Recurse
  • 抱歉 powershell :) xcopy C:\temp D:\mybackup /e
  • @boxdog 不,这只会复制两个根文件。
  • 我建议使用 RoboCopy。
  • @StefanLippeck。奇怪 - 当我测试它时工作。也许我错过了什么。无论如何,镜像大型文件夹结构是我不喜欢在本机 PowerShell 中执行的少数任务之一。我有一些与 RoboCopy 类似的定期运行的备份作业:RoboCopy /mir <source_dir> <dest_dir>

标签: powershell copy-item


【解决方案1】:

我真的更喜欢 XcopyRoboCopy 来做那些工作,但如果你真的想使用 Copy-Item:

Get-ChildItem C:\temp -Recurse | % {Copy-Item $_.FullName D:\mybackup}

使用 Xcopy:

xcopy C:\temp D:\mybackup /e

使用 RoboCopy:

robocopy C:\temp D:\mybackup /e

【讨论】:

  • 这让我已经更接近了一点,但在这种情况下,所有文件都以 D:\backup\ 结尾(如果有同名文件,它们会相互覆盖) - 但是你让我朝着正确的方向前进。我很快就会提出我的解决方案
【解决方案2】:

另一种解决方法可能是使用Copy-Item,后跟Move-Item

Copy-Item 'C:\temp\' -Destination 'D:\' -Recurse
Move-Item 'D:\temp\' -Destination 'D:\mybackup'

这确实有一些警告

  • D:\temp 尚不存在。如果是这样,您最终会覆盖/移动其他文件
  • D:\mybackup 尚不存在

【讨论】:

    【解决方案3】:

    感谢@Avshalom 的输入,我找到了答案。 我为自己写了一个小函数以备将来使用:

    function myCopyFolder([string] $sourceFolder, [string] $destFolder) {
        $i = 0
        Get-ChildItem $sourceFolder -Recurse | % {
            $destName = $_.FullName
            $destName = $destName.Replace($sourceFolder, '')
            Write-Host $_.FullName -Destination (Join-Path $destFolder $destName)
            $i = $i + 1
        }
        write-host $i 'files' copied
    }
    

    现在我得到了一个完整的副本,就像 xcopy 一样。我也尝试实现过滤器,但如果需要,我必须找到一种方法来单独复制文件夹。 - 它可以满足我的需求。

    我添加了按文件类型过滤:(不会使用过滤器复制空文件夹)

    function myCopyFolder([string] $sourceFolder, [string] $destFolder, [string] $filter) {
        $i = 0
        Get-ChildItem $sourceFolder -Recurse -Filter $filter | % {
            $destName = $_.FullName
            $destName = $destName.Replace($sourceFolder, '')
            $subFolder = $destName.Replace($_.Name, '').Replace('\','')
            if ($subFolder -ne '') {
                if (-not (Test-Path (Join-Path $destFolder $subFolder))) {
                    mkdir (Join-Path $destFolder $subFolder)
                }
            }
            Copy-Item $_.FullName -Destination (Join-Path $destFolder $destName)
            $i = $i + 1
        }
        write-host $i 'files' copied
    }
    

    【讨论】:

    • 顺便说一句,函数定义中的 [string] 类型修饰符可能没有达到您的预期 - 它们并不意味着您只能传入字符串,而是表示“我会接受任何字符串或可以转换为字符串的东西”。由于 .NET 中的每个对象都有一个 ToString() 方法(IntDateTimeWebClientGuid 等),因此您传递的任何内容都将被接受(即转换为字符串)并且结果行为可能是出乎意料,甚至是灾难性的。
    猜你喜欢
    • 2016-02-27
    • 2012-09-08
    • 1970-01-01
    • 2022-10-05
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    相关资源
    最近更新 更多