将文件移动到父文件夹名称匹配的新位置

Move File to new location where Parent Folder Name Matches

问题

我正在开发我的应用程序中的回滚功能,我将文件从 backup/rollback 目录复制到目标文件夹。听起来很简单,这就是它变得复杂的地方。由于所有文件共享相同或相似的名称,我使用父文件夹作为锚点来帮助强制执行唯一位置。

我想基本上递归地搜索一个目录,只要文件夹名称与对象的父目录匹配,就将该对象的副本粘贴到该文件夹​​中,覆盖与该对象共享名称的任何文件。

一种更直观的表示方式是:

$Path = C:\Temp\MyBackups\Backup_03-14-2017
$destination = C:\SomeDirectory\Subfolder
$backups = GCI -Path "$Path\*.config" -Recursive

foreach ($backup in $backups) {
    Copy-Item -Path $backup -Destination $destination | Where-Object {
        ((Get-Item $backup).Directory.Name) -match "$destination\*"
    }
}

但是,上述方法不起作用,none 我的研究发现与我正在尝试做的事情有很大的相似之处。

问题

有谁知道如何使用 PowerShell 将项目从一个位置复制到另一个位置,其中复制项目的父文件夹与目标中的文件夹相匹配?

你可能想多了。如果您要从网站备份 web.config 文件,我强烈建议您使用 SiteID 作为备份文件夹。然后只需利用它作为找到正确文件夹的方法,以便在您想要回滚时将 web.config 文件复制到其中。

理想情况下,在处理任何一组项目(在本例中为网站)时,请尝试为这些项目找到唯一标识符。 SiteIDs 是理想的选择。

$Path = C:\Temp\MyBackups\Backup_03-14-2017  #In this directory store the web.config's in directories that match the SiteID of the site they belong to
#For example, if the site id was 5, then the full backup directory would be: C:\Temp\MyBackups\Backup_03-14-2017 
$backups = Get-ChildItem -Path $Path -Include *.config -Recurse

foreach ($backup in $backups) 
{
    $backupId = $backup.Directory.Name
    $destination = (Get-Website | where {$_.id -eq $backupId}).physicalPath

    Copy-Item -Path $backup -Destination $destination 
}

枚举备份文件,将源基本路径替换为目标基本路径,然后移动文件。如果只想替换现有文件,请测试目标是否存在:

Get-ChildItem -Path $Path -Filter '*.config' -Recursive | ForEach-Object {
    $dst = $_.FullName.Replace($Path, $destination)
    if (Test-Path -LiteralPath $dst) {
        Copy-Item -Path $_.FullName -Destination $dst -Force
    }
}

如果要恢复目标中丢失的文件,请确保先创建丢失的目录:

Get-ChildItem -Path $Path -Filter '*.config' -Recursive | ForEach-Object {
    $dst = $_.FullName.Replace($Path, $destination)
    $dir = [IO.Path]::GetDirectoryName($dst)
    if (-not (Test-Path -LiteralPath $dir -PathType Container)) {
        New-Item -Type Directory -Path $dir | Out-Null
    }
    Copy-Item -Path $_.FullName -Destination $dst -Force
}