Элемент копирования Powershell 2, который создает папку, если она не существует - PullRequest
57 голосов
/ 23 апреля 2010
$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\, если она не существует?

Ответы [ 8 ]

95 голосов
/ 13 января 2012

В PowerShell 2.0 по-прежнему невозможно получить командлет Copy-Item для создания папки назначения, вам потребуется код, подобный следующему:

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

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

Если вы используете -Recurse в Copy-Item, он создаст все подпапки исходной структуры в месте назначения, но не создаст фактическую папку назначения, даже с -Force.

72 голосов
/ 23 апреля 2010

Да, добавьте параметр -Force.

copy-item $from $to -Recurse -Force
10 голосов
/ 17 февраля 2016

В 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.

3 голосов
/ 01 июня 2017
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
    } 
}
3 голосов
/ 01 июля 2016
  $filelist | % {
    $file = $_
    mkdir -force (Split-Path $dest) | Out-Null
    cp $file $dest
  } 
2 голосов
/ 09 марта 2019

Вот пример, который работал для меня. У меня был список из 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 }
}
2 голосов
/ 09 сентября 2016

Мой фаворит - использовать класс .Net [IO.DirectoryInfo], который заботится о некоторой логике. Я на самом деле использую это для многих подобных задач сценариев. У него есть метод .Create (), который создает несуществующие каталоги, без ошибок, если они есть.

Поскольку это все еще двухэтапная проблема, я использую псевдоним foreach, чтобы упростить его. Для отдельных файлов:

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

Что касается совпадения нескольких файлов / каталогов, я бы использовал RoboCopy поверх xcopy. Удалите «*» из вашего и просто используйте:

RoboCopy.exe $from $to *

Вы все еще можете добавить / r (Рекурс), / e (Рекурс, включая Пустой), и есть 50 других полезных переключателей.

Редактировать: Оглядываясь назад, это кратко, но не очень читабельно, если вы не часто используете код. Обычно я делю его на две части, например:

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

Кроме того, DirectoryInfo является типом свойства Parent для FileInfo , поэтому, если ваш $ - - файл, вы можете использовать их вместе:

([IO.FileInfo]$to).Parent.Create()
cp $from $to
1 голос
/ 26 марта 2016

Я споткнулся здесь дважды, и в последний раз это была уникальная ситуация, и хотя я отказался от использования 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")) }

Надеюсь, это кому-нибудь поможет.

...