【问题标题】:How to copy local files AND PATHS to network share using PowerShell?如何使用 PowerShell 将本地文件和路径复制到网络共享?
【发布时间】:2020-12-08 03:02:32
【问题描述】:

使用 PowerShell,我尝试从本地驱动器通过管道传输文件列表,以便 Copy-Items 可以将它们复制到网络文件夹。以下语句确实找到了我需要的文件,并复制了它们。但是,所有路径信息都会丢失,并且它们都最终在同一个文件夹中。我希望每个文件都以相对路径方式保存在目标位置,其文件路径来自本地磁盘。

因此,例如“c:\users\user_name\Documents\file_1.txt”应复制到“\\server\share\my_folder\users\user_name\Documents\file_1.txt”

事实证明,我的搜索毫无结果。可以修改此语句以实现此目的吗?

Get-ChildItem -Path c:\users\user_name -r | ? {!($_.psiscontainer) -AND $_.lastwritetime -gt (get-date).date} | %{Copy-Item -Path $_.fullname -destination "\\server\share\my_folder" -Recurse -Force -Container}

编辑:

看来 Copy-Item 应该能够做到这一点。以下命令有效:

Copy-Item -Path c:\users\user_name\Documents -Destination "\\server\share\my_folder" -recurse -Force

此命令复制 c:\users\user_name\Documents 及其下的子文件夹中的所有文件、子文件夹和文件。然后它在网络共享上重新创建相对目录结构。似乎第一个命令中的 $_.fullname 参数没有以类似的方式处理。我肯定不会以预期的方式将文件列表传递给 Copy-Item。还有其他建议吗?

【问题讨论】:

  • 我建议您改为查看robocopy
  • @iRon - 这不能回答我的问题。我有相对路径信息,我正在尝试在网络文件共享上重新创建该结构。下面 Doug Maurer 指出 Copy-Item 命令无法完成此操作。所以,我想我必须推出自己在 MS-DOS 6.0 中存在的功能。令人失望。

标签: powershell copy-item


【解决方案1】:

有几件事我们应该回顾一下。首先,如果您只想要文件,您可以删除 !$_.psiscontainer 检查并将-file 添加到Get-Childitem 命令。接下来,如果您打算复制早于Get-Date 的文件,则比较需要为-lt。至于在目标中创建目录结构,您需要自己制作。您可以通过将c: 从路径中剥离并像这样使用*-Path cmdlet 来实现它。

$source      = 'c:\users\user_name\Documents'
$destination = '\\server\share\my_folder'

Get-ChildItem -Path $source -File -Recurse |
    Where-Object {$_.lastwritetime -lt (get-date).date} |
        ForEach-Object {
            $destdir = Join-Path $destination (Split-Path $_.FullName -Parent).Substring(2)
            
            If(-not(Test-Path $destdir))
            {
                Write-Host Making directory $destdir -ForegroundColor Cyan
                $null = New-Item -Path $destdir -ItemType Directory
            }
            
            Write-Host Copying file $_.name to $destdir -ForegroundColor Green
            Copy-Item $_.FullName -Destination $destdir
        }

但是,正如 Bill_Stewart 所说,robocopy 或其他工具可能更合适。 Robocopy 肯定会快得多,所以如果您需要它来处理大量数据,我会朝着这个方向努力。

【讨论】:

  • 不,我不想要早于 Get-Date 的文件。我的问题如何表明我的布尔比较与我写的相反?我的问题表明我正在返回我想要的文件并复制它们。他们只是没有像我希望的那样被复制。我包括 !$_.psiscontainer 因为我试图复制文件和文件夹。因此,考虑到您重新处理的问题和 Bill_Stewart 上面的评论,我的问题的答案似乎是“否”。我的语句的 Copy-Item 部分无法重新创建文件路径。
  • 因此您希望将来制作尚不存在的文件。此外,!$_.psiscontainer 表示不是目录,因此您将其过滤掉。
  • 1) 这将在一天结束时运行并获取当天创建/更新的文件。我正在尝试创建增量备份策略。正如我所说,我正在寻找我需要的文件。 2) 不是目录 - 我不想将更新的目录通过管道传输到 Copy-Item,因为这将导致完整的目录副本。该命令的工作原理是它列出了我要复制的文件: Get-ChildItem -Path c:\users\tlash -r | ? {!($_.psiscontainer) -AND $_.lastwritetime -gt (get-date).date}。我只是无法获得复制的路径。
  • 我相信您对副本项目的看法是正确的。如果你递归地创建一个文件夹,它会创建子目录,但是对于每个文件,除了我建议的之外,我不知道其他方法。
【解决方案2】:

正如提到的使用Set-Location(参见:Get relative path of files in sub-folders from the current directory):

Set-Location c:\users\user_name
Get-ChildItem -Recurse |
  Where-Object { !($_.psiscontainer) -AND $_.lastwritetime -gt (get-date).date } |
    Foreach-Object {
        $Destination = Join-Path \\server\share\my_folder ("$_" | Resolve-Path -Relative)
        New-Item -ItemType File -Path $destination -Force
        Copy-Item -Path "$_" -Destination $Destination -Force
    }

【讨论】:

  • 单行不工作。它确实返回了正确的文件列表,但 Copy-Item 组件仍然失败:“ObjectNotFound: (c:\users\user_name\test.txt:string) [Resilve-Path], ItemNotFoundException.test.txt is in Documents.
  • 抱歉,您需要删除最后一个 -Recurse 和 -Container 开关,因为它们已经由 Get-ChildItem 和 Where-Object cmdlet 定义(我已经更新了答案)。跨度>
  • 同样的错误。当我使用这个 == Set-Location c:\users\user_name; Get-ChildItem -Recurse | ? { !($_.psiscontainer) -AND $_.lastwritetime -gt (get-date).date } | Resolve-Path -Relative == 我得到:.\Documents\test.txt。但是,Copy-Item 仍在尝试复制不存在的 c:\users\user_name\test.txt。无法使 Copy-Items 识别正在传递的路径。
  • 好的,这行得通 - Set-Location c:\users\user_name; Get-ChildItem -Recurse | ? { !($_.psiscontainer) -AND $_.lastwritetime -gt (get-date).date } | % {Copy-Item $_.fullname -destination (Join-Path '\\server\share\my_folder' ($_ | Resolve-Path -Relative)) -Force } 但仅当目标文件夹“文档”已经存在时。这么近!
  • 这个“文件夹”问题实际上在Should Copy-Item create the destination directory structure? 中有所描述。我在答案中加入了这个。我确实删除了 oneliner,因为不再清楚它的作用,但如果您确实需要一个衬里(您也可以将多行粘贴到您的 IDE 中),您可以简单地用分号 (;) 连接语句。跨度>
【解决方案3】:

好的,这是一个相当大的挑战,但我终于找到了一个机制。感谢@iRob 为我指出了一个潜在的解决方案。我无法让他的代码在目的地创建相对路径,但能够扩展他的概念。我最终添加了一个 New-Item 命令(通过Powershell 2 copy-item which creates a folder if doesn't exist 找到)和一个拆分路径(在这里找到Copy a list of files to a directory)。 Split-Path 从连接路径中切出文件名,然后通过 New-Item 命令创建该路径。最后,Copy-Item 有了一个复制文件的地方。所以从这个意义上说,@Doug Maurer 也是正确的,Copy-Item 自己不会这样做。在 Copy-Item 命令可以成功运行之前,需要进行一些额外的准备。

Set-Location c:\users\user_name; Get-ChildItem -Recurse | ? { !($_.psiscontainer) -AND $_.lastwritetime -gt (get-date).date } | % {Copy-Item $_.fullname -destination (New-Item -type directory -force ((Join-Path '\\server\share\my_folder' ($_ | Resolve-Path -Relative)) | Split-Path -Parent)) -Force}

恕我直言,在 MS-DOS 6.0 中微不足道的东西(xcopy /D:08-20-2020 /S c:\users\user_name*.* \server\share\my_folder)在 PowerShell 中应该不会那么困难。似乎应该有一个更简单的方法。现在我想起来了,可能应该坚持使用 xcopy 而不是潜入这个兔子洞。 PowerShell 看起来很闪亮。

【讨论】:

    猜你喜欢
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多