Copy-Item не копирует в правильный целевой каталог - PullRequest
0 голосов
/ 24 мая 2019

Я пытаюсь скопировать структуру каталогов с помощью скрипта PowerShell.Я хочу исключить определенный каталог.

Моя структура каталогов выглядит следующим образом:

C:\
└───murks
    ├───murks_source
    │   │   test1.txt
    │   │   test2.txt
    │   │
    │   ├───sub
    │   │       subtest1.txt
    │   │       subtest2.txt
    │   │       subtest3.txt
    │   │
    │   └───sub2
    │           sub2test.txt
    │
    └───murks_target

Теперь, когда я запускаю скрипт, он не создает подкаталог «sub2» сподчиненные файлы.Вместо этого он копирует все файлы (в том числе из подкаталога «sub2») непосредственно в каталог murks_target_directory.Я не понимаю этого поведения, так как пока что "-ExpandProperty FullName" -часть выглядит хорошо.

Любая помощь или подсказки высоко ценятся.Заранее спасибо!

Мой скрипт выглядит так:

$rootFolderPath = 'C:\murks\murks_source'
$excludeDirectories = ("sub");

function Exclude-Directories
{
    process
    {
        $allowThrough = $true
        foreach ($directoryToExclude in $excludeDirectories)
        {
            $directoryText = "*\" + $directoryToExclude
            $childText = "*\" + $directoryToExclude + "\*"
            if (($_.FullName -Like $directoryText -And $_.PsIsContainer) `
                -Or $_.FullName -Like $childText)
            {
                $allowThrough = $false
                break
            }
        }

        if ($allowThrough)
        {
            return $_
        }
    }
}

Get-ChildItem $rootFolderPath -Recurse | Exclude-Directories | Select -ExpandProperty FullName | Copy-Item -Destination C:\murks\murks_target -Force

Ответы [ 3 ]

0 голосов
/ 24 мая 2019

Следующая пользовательская функция должна делать то, что вы хотите:

function Copy-Path {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
        [ValidateScript({Test-Path -Path $_ -PathType Container})]
        [string]$Source,

        [Parameter(Position = 1)]
        [string]$Destination,

        [string[]]$ExcludeFolders = $null,
        [switch]$IncludeEmptyFolders
    )
    $Source      = $Source.TrimEnd("\")
    $Destination = $Destination.TrimEnd("\")

    Get-ChildItem -Path $Source -Recurse | ForEach-Object {
        if ($_.PSIsContainer) {
            # it's a folder
            if ($ExcludeFolders.Count) {
                if ($ExcludeFolders -notcontains $_.Name -and $IncludeEmptyFolders) {
                    # create the destination folder, even if it is empty
                    $target = Join-Path -Path $Destination -ChildPath $_.FullName.Substring($Source.Length)
                    if (!(Test-Path $target -PathType Container)) {
                        Write-Verbose "Create folder $target"
                        New-Item -ItemType Directory -Path $target | Out-Null
                    }
                }
            }
        }
        else {
            # it's a file
            $copy = $true
            if ($ExcludeFolders.Count) {
                # get all subdirectories in the current file path as array
                $subs = $_.DirectoryName.Replace($Source,"").Trim("\").Split("\")
                # check each sub folder name against the $ExcludeFolders array
                foreach ($folderName in $subs) {
                    if ($ExcludeFolders -contains $folderName) { $copy = $false; break }
                }
            }

            if ($copy) {
                # create the destination folder if it does not exist yet
                $target = Join-Path -Path $Destination -ChildPath $_.DirectoryName.Substring($Source.Length)
                if (!(Test-Path $target -PathType Container)) {
                    Write-Verbose "Create folder $target"
                    New-Item -ItemType Directory -Path $target | Out-Null
                }
                Write-Verbose "Copy file $($_.FullName) to $target"
                $_ | Copy-Item -Destination $target -Force
            }
        }
    }
}

Когда это будет на месте, используйте это так:

Copy-Path -Source 'C:\murks\murks_source' -Destination 'C:\murks\murks_target' -ExcludeFolders 'sub' -Verbose

Где параметр -ExcludeFolders может быть массивом следующих имен для пропуска.
Добавление параметра переключателя IncludeEmptyFolders также создаст пустые папки в месте назначения. Если пропущены, пустые папки не будут скопированы.

Используя структуру вашего примера, вы получите

C:\murks\murks_target
|   test1.txt
|   test2.txt
|
\---sub2
        sub2test.txt
0 голосов
/ 24 мая 2019

Все это может быть достигнуто с помощью одной строки.

$source = 'C:\murks\murks_source'
$dest = 'C:\murks\murks_target'

Копирование всего, кроме папок 'Sub' и их содержимого:

Get-ChildItem -Path $source -Recurse | ? {$_.Name -notmatch 'sub'} | Copy-Item -Destination $dest

Сохранение структуры папок, включая все файлы:

Get-ChildItem -Path $source | Copy-Item -Destination $dest -Recurse -Container

Копировать структуру папок, но без файлов ...

Get-ChildItem -Path $source | ? {$_.PSIsContainer} | Copy-Item -Destination $dest -Recurse -Exclude '*.*'

Очевидно, что вы можете объединить пример 1 и пример 2, чтобы сохранить структуру папок / файлов, а также исключить любой каталогВы хотите по имени, подстановочный знак и т. д.

0 голосов
/ 24 мая 2019

Я почти нашел ответ, который предоставил бы вам всю функциональность.

$from = "C:\murks\murks_source"
$to = "C:\murks\murks_target"
$exclude = Get-ChildItem -Path C:\murks\murks_source\sub2\ -Depth 10
Copy-Item $from -Exclude $exclude -Destination $to -Recurse

Он будет игнорировать все файлы, кроме структуры папок.Структура папок будет скопирована, но пуста.

Надеюсь, это поможет.

...