PowerShell:从 SMB 共享下载文件列表而不覆盖

PowerShell: Download a List of Files from SMB Shares without Overwriting

我想从远程网络共享下载预定义文件列表,而不覆盖具有相同名称的本地文件。我主要通过使用 Bitstransfer 模块在 PowerShell 中使用此功能。您可以在代码中看到 C:\SMB\paths.txt 指向包含远程 SMB 路径的本地文件。

SMBBulkDownload.ps1:

Import-Module bitstransfer

foreach($line in Get-Content C:\SMBDump\paths.txt) {
    $sourcePath = $line
    $destPath = "C:\SMBDump\"
    Start-BitsTransfer -Source $sourcePath -Destination $destPath     
}

其中 C:\SMB\paths.txt 包含(示例片段):

\10.17.202.21\some\dir\app.config
\10.19.197.68\some\dir\app.config
\10.28.100.34\some\dir\Web.config

上面的代码可以正确下载文件如果它们有不同的文件名。在文件名相同的情况下,传输 returns 一个 ACCESSDENIED 错误。这可能是由于模块不支持同名文件副本,或者是由于同时复制同名文件的竞争条件。这很不幸,因为我的工作需要批量下载许多同名的不同文件,例如 App.Config、Web.Config 等

错误:

Start-BitsTransfer : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

有没有人有解决这个同名文件复制块的解决方案?我理想的解决方案是将具有冗余名称的文件复制到带有“_1”或“_2”或_后缀的同一目录中。

假设你的错误源于你的文件名理论,这将是一个值得尝试的东西......

您的路径都有一个唯一的组成部分:服务器 IP 地址或名称。我建议为每个地址创建一个子目录或将其附加到名称中。

按主机组织在文件夹中的文件

foreach($line in Get-Content C:\SMBDump\paths.txt) {
    $hostName = ([uri]$line).Host
    $fileName = Split-Path $line -Leaf
    $destPath = "C:\SMBDump$hostName$fileName"
    Start-BitsTransfer -Source $sourcePath -Destination $destPath     
}

具有主机命名前缀的同一文件夹中的文件

foreach($line in Get-Content C:\SMBDump\paths.txt) {
    $hostName = ([uri]$line).Host
    $fileName = Split-Path $line -Leaf
    $destPath = "C:\SMBDump$hostName-$fileName"
    Start-BitsTransfer -Source $sourcePath -Destination $destPath     
}

这应该不会导致名称冲突,只要您的文件包含唯一值,就不会有任何争用。

Matt 的方法是保持唯一文件路径并允许您将文件追溯到其源服务器的方法。

要从字面上回答这个问题,您需要检查您要复制的文件是否存在,并更改路径以避免冲突。

Import-Module bitstransfer

foreach($line in Get-Content C:\SMBDump\paths.txt) {
    $sourcePath = $line
    $destPath = "C:\SMBDump\"      
    $fileName = Split-Path -Path $line -leaf

    if(Test-Path "$destPath$fileName"){
        $extension = [io.path]::GetExtension($fileName)
        $basename  = [io.path]::GetFileNameWithoutExtension($fileName)
        $i = 1

        do{
            $fileName  = "${basename}_$i$extension"
            if(-not (Test-Path "$destPath$fileName")){
                $next = $false
            }else{
                $next = $true
                $i++
            }

        }while($next -eq $true)

    }

    Start-BitsTransfer -Source $sourcePath -Destination "$destPath$fileName"    
}