74
$from = "\\something\1 XLS\2010_04_22\*"
$to =  "c:\out\1 XLS\2010_04_22\"
copy-item $from $to -Recurse 

如果c:\out\1 XLS\2010_04_22\确实存在,则此方法有效。c:\out\1 XLS\2010_04_22\如果它不存在,是否可以使用单个命令创建?

4

10 回答 10

115

在 PowerShell 2.0 中,仍然无法获取 Copy-Item cmdlet 来创建目标文件夹,您需要如下代码:

$destinationFolder = "C:\My Stuff\Subdir"

if (!(Test-Path -path $destinationFolder)) {New-Item $destinationFolder -Type Directory}
Copy-Item "\\server1\Upgrade.exe" -Destination $destinationFolder

如果在 Copy-Item 中使用 -Recurse,它将在目标中创建源结构的所有子文件夹,但不会创建实际的目标文件夹,即使使用 -Force。

于 2012-01-13T12:45:00.840 回答
85

是的,添加-Force参数。

copy-item $from $to -Recurse -Force
于 2010-04-23T07:36:01.737 回答
17

在 PowerShell 3 及更高版本中,我将 Copy-Item 与 New-Item 结合使用。

copy-item -Path $file -Destination (new-item -type directory -force ("C:\Folder\sub\sub\" + $newSub)) -force -ea 0

我在第 2 版中没有尝试过。

于 2016-02-17T16:09:42.013 回答
3
  $filelist | % {
    $file = $_
    mkdir -force (Split-Path $dest) | Out-Null
    cp $file $dest
  } 
于 2016-07-01T11:48:55.953 回答
3
function Copy-File ([System.String] $sourceFile, [System.String] $destinationFile, [Switch] $overWrite) {

    if ($sourceFile -notlike "filesystem::*") {
        $sourceFile = "filesystem::$sourceFile" 
    }

    if ($destinationFile -notlike "filesystem::*") {
        $destinationFile = "filesystem::$destinationFile" 
    }

    $destinationFolder = $destinationFile.Replace($destinationFile.Split("\")[-1],"")

    if (!(Test-Path -path $destinationFolder)) {
        New-Item $destinationFolder -Type Directory
    }

    try {
        Copy-Item -Path $sourceFile -Destination $destinationFile -Recurse -Force
        Return $true 
    } catch [System.IO.IOException] {
        # If overwrite enabled, then delete the item from the destination, and try again:
        if ($overWrite) {
            try {
                Remove-Item -Path $destinationFile -Recurse -Force        
                Copy-Item -Path $sourceFile -Destination $destinationFile -Recurse -Force 
                Return $true
            } catch {
                Write-Error -Message "[Copy-File] Overwrite error occurred!`n$_" -ErrorAction SilentlyContinue
                #$PSCmdlet.WriteError($Global:Error[0])
                Return $false
            }
        } else {
            Write-Error -Message "[Copy-File] File already exists!" -ErrorAction SilentlyContinue
            #$PSCmdlet.WriteError($Global:Error[0])
            Return $false
        }
    } catch {
        Write-Error -Message "[Copy-File] File move failed!`n$_" -ErrorAction SilentlyContinue
        #$PSCmdlet.WriteError($Global:Error[0]) 
        Return $false
    } 
}
于 2017-06-01T18:17:20.457 回答
3

这是一个对我有用的例子。我有一个文本文件中大约 500 个特定文件的列表,包含在大约 100 个不同的文件夹中,我应该将其复制到备份位置,以防以后需要这些文件。文本文件包含完整路径和文件名,每行一个。就我而言,我想从每个文件名中去掉驱动器号和第一个子文件夹名。我想将所有这些文件复制到我指定的另一个根目标文件夹下的类似文件夹结构。我希望其他用户觉得这很有帮助。

# Copy list of files (full path + file name) in a txt file to a new destination, creating folder structure for each file before copy
$rootDestFolder = "F:\DestinationFolderName"
$sourceFiles = Get-Content C:\temp\filelist.txt
foreach($sourceFile in $sourceFiles){
    $filesplit = $sourceFile.split("\")
    $splitcount = $filesplit.count
    # This example strips the drive letter & first folder ( ex: E:\Subfolder\ ) but appends the rest of the path to the rootDestFolder
    $destFile = $rootDestFolder + "\" + $($($sourceFile.split("\")[2..$splitcount]) -join "\")
    # Output List of source and dest 
    Write-Host ""
    Write-Host "===$sourceFile===" -ForegroundColor Green
    Write-Host "+++$destFile+++"
    # Create path and file, if they do not already exist
    $destPath = Split-Path $destFile
    If(!(Test-Path $destPath)) { New-Item $destPath -Type Directory }
    If(!(Test-Path $destFile)) { Copy-Item $sourceFile $destFile }
}
于 2019-03-09T01:40:16.770 回答
2

我最喜欢的是使用 .Net [IO.DirectoryInfo] 类,它负责一些逻辑。我实际上将它用于许多类似的脚本挑战。它有一个 .Create() 方法,可以创建不存在的目录,如果存在则不会出错。

由于这仍然是一个两步问题,我使用 foreach 别名来保持简单。对于单个文件:

[IO.DirectoryInfo]$to |% {$_.create(); cp $from $_}

至于您的多文件/目录匹配,我会使用 RoboCopy 而不是 xcopy。从您的 from 中删除“*”,然后使用:

RoboCopy.exe $from $to *

您仍然可以添加 /r(递归)、/e(包括空的递归),还有 50 个其他有用的开关。

编辑:回头看它很简洁,但如果你不经常使用代码,它的可读性就不是很高。通常我把它分成两部分,像这样:

([IO.DirectoryInfo]$to).Create()
cp $from $to

另外,DirectoryInfoFileInfo的 Parent 属性的类型,所以如果你的$to是一个文件,你可以一起使用它们:

([IO.FileInfo]$to).Parent.Create()
cp $from $to
于 2016-09-09T14:27:02.830 回答
1

我在这里绊倒了两次,最后一次是一个独特的情况,即使我放弃使用copy-item我想发布我使用的解决方案。

除了具有完整路径的文件之外,只有一个列表,并且在大多数情况下,这些文件没有扩展名。该-Recurse -Force选项对我不起作用,因此我放弃了copy-item功能并使用 xcopy 回到下面的内容,因为我仍然希望将其保留为单行。最初我与 Robocopy 绑定,但它显然在寻找文件扩展名,因为我的许多人没有扩展名,所以它认为它是一个目录。

$filelist = @("C:\Somepath\test\location\here\file","C:\Somepath\test\location\here2\file2")

$filelist | % { echo f | xcopy $_  $($_.Replace("somepath", "somepath_NEW")) }

希望它可以帮助某人。

于 2016-03-25T22:15:43.150 回答
1
$file | Copy-Item -Destination (New-Item -Force -Type Directory -Path $directoryName)
于 2021-03-12T00:00:24.777 回答
0

我修改了@FrinkTheBrave 的答案以创建子目录并解析相对路径:

$src_root = Resolve-Path("./source/path/")
$target_root = Resolve-Path("./target/path/")
$glob_filter = "*.*"
Get-ChildItem -path $src_root -filter $glob_filter -recurse | 
  ForEach-Object {
        $target_filename=($_.FullName -replace [regex]::escape($src_root),$target_root) 
        $target_path=Split-Path $target_filename
        if (!(Test-Path -Path $target_path)) {
            New-Item $target_path -ItemType Directory
        }
        Copy-Item $_.FullName -destination $target_filename
    }
于 2020-11-14T22:07:02.727 回答