默认情况下,Copy-Item会被覆盖

时间:2017-03-21 15:32:13

标签: powershell

我期望从以下代码中获得的行为是:

  1. 获取源目录中的文件列表。
  2. 循环并将每个文件复制到备份目标,只有它尚不存在。

    if (!(Test-Path C:\Folder\Destination)) {
       New-Item -ItemType Directory -Force -Path C:\Folder\Destination
    }
    
    $originalfiles = Get-ChildItem -Path  "C:\Folder\Source"
    $originalfiles
    
    foreach ($file in $originalfiles) {
        Write-Host
        Write-Host File Name: -ForegroundColor DarkYellow
        Write-Host $file.Name
        Write-Host File Path: -ForegroundColor DarkYellow
        Write-Host $file.FullName
    
        $src = $file.FullName
        $dest = "C:\Folder\Destination\$($file.Name)"
    
        Copy-Item $src $dest
    }
    
  3. 除非您指定Copy-Item标志,否则我认为-Force cmdlet默认为不覆盖。这是我以前在遇到我想要覆盖的情况时会看到的行为。

    另外,我认为它可能是foreach循环的引入,但我尝试了自己的复制命令,使用单个文件的硬编码路径,它仍然是相同的。

    我应该重启我的IDE还是我忽略了一个错误?

5 个答案:

答案 0 :(得分:5)

如有疑问,请阅读documentation

  

<强> -Force

     

允许cmdlet复制无法以其他方式更改的项目,例如复制只读文件或别名。

Copy-Item的默认行为是替换现有项目。如果例如目标文件具有readonly属性集,则-Force开关仅用于强制替换。

您可以使用-ConfirmCopy-Item执行操作之前收到提示,或者您可以使用-WhatIf查看cmdlet的用途。

答案 1 :(得分:5)

似乎是Copy-Item将项目复制到目标的预期行为,即使它已存在于目标中。我建议测试一下目标文件路径是否存在,如果文件尚不存在则只复制该文件。

$destinationPath = 'C:\tryout\destination';
if (!(Test-Path $destinationPath)) 
{
   New-Item -ItemType Directory -Force -Path $destinationPath;
}

$sourcePath = 'C:\tryout\source';
$originalfiles = Get-ChildItem -Path $sourcePath;
$originalfiles;

foreach ($file in $originalfiles) 
{
    Write-Host;
    Write-Host File Name: -ForegroundColor DarkYellow;
    Write-Host $file.Name;
    Write-Host File Path: -ForegroundColor DarkYellow;
    Write-Host $file.FullName;

    $src = $file.FullName;
    $dest = "C:\tryout\destination\$($file.Name)";

    if (!(Test-Path $dest))
    {
        Copy-Item $src -Destination $dest;
    }
}

答案 2 :(得分:4)

旧的,但是我发现有一个简短的表达式可以做到这一点:

Copy-Item (Join-Path $dir_from "*") $dir_to -Exclude (Get-ChildItem $dir_to)

它将所有文件从$dir_from复制到$dir_to,但不(-Exclude部分)复制名称已经在$dir_to中的文件

答案 3 :(得分:1)

仅当目标位置中不存在文件时才复制文件递归的版本。如果需要,它将创建子文件夹。它不会创建空文件夹。如果需要它们,请从-File

中删除Get-ChildItem
$srcDirPath = "C:\SourceDir"
$destDirPath = "C:\DestinationDir"
# Get list of files from source dir recursively. It doesn't list hidden files by default 
# Remove where{} if you don't need to exclude files by name, in this sample I exclude all README.md in any folders
$fileList = Get-ChildItem -Path $srcDirPath -File -Recurse | where{$_.Name -ne 'README.md'}
# get source dir path just in case to exactly match Get-ChildItem paths
$fullSrcDirPath = (Get-Item -Path $srcDirPath).FullName
foreach($file in $fileList)
{
    # build full destination file path
    $destFilePath = $destDirPath + $file.FullName.Remove(0, $fullSrcDirPath.Length)
    # proceed only if file doesn't exist in destination
    if(-not (Test-Path "$destFilePath"))
    {
        # Copy-Item can't create subfolders, so create subfolder if it doesn't exist
        # Get full destination folder path for current file
        $curDestDir = Split-Path $destFilePath -Parent
        if(-not (Test-Path "$curDestDir"))
        {
            # create subfolder(s)
            # $res here suppresses output
            $res = New-Item -Path "$curDestDir" -ItemType "directory"
        }
        Copy-Item -Path $file.FullName -Destination "$destFilePath"
    }
}

答案 4 :(得分:0)

如果您担心被覆盖会很快发生:

function mycopy { 
  if (! (test-path $args[1])) { copy $args[0] $args[1] } else { 'file exists' } 
}