Сценарий развертывания XCOPY - как включить определенные файлы?

Мне нужно скопировать только определенные части папки с помощью Powershell, в частности этот список:

$files = @("MyProgram.exe",
           "MyProgram.exe.config",
           "MyProgram.pdb",
           ".\XmlConfig\*.xml")

В удобочитаемой форме: 3 конкретных файла MyProgram.* в корне целевой папки и все файлы XML в папке XmlConfig, которая сама находится в корне исходного пути (..\bin\Release\ в моем случае). Папка XmlConfig должна быть создана в месте назначения, если она не существует.

Что я пробовал:

(1) Я пробовал следующее, но это не сработало, т.е. по пути назначения не было создано ни папки, ни файлов:

Copy-Item -Recurse -Path "..\bin\Release\" -Destination ".\Test\" -Include $files

(2) Когда -Include удаляется, вся структура папок успешно создается, включая подпапки и файлы:

Copy-Item -Recurse -Path "..\bin\Release\" -Destination ".\Test\"

Должно быть, что-то не так с моим пониманием того, как работает фильтр -Include:

(3) Я проверил предположение, что -Include нужен массив подстановочных знаков, но это тоже не сработало:

$files = @("*MyProgram.exe*",
           "*MyProgram.exe.config*",
           "*MyProgram.pdb*",
           "*.\XmlConfig\*.xml*")

Посоветуйте, пожалуйста, как правильно сделать Copy-Item в моем случае.

ОБНОВЛЕНИЕ (на основе ответов ниже):

Я ищу общую реализацию, которая принимает массив строк. Это открывает возможность разместить все необходимые файлы/пути в одном месте для удобного редактирования, чтобы человек, не знающий Powershell, мог понять и изменить его по мере необходимости. Таким образом, в конце концов, это будет один сценарий для выполнения развертывания XCOPY для любого проекта, при этом входной файл будет единственной переменной частью. Для приведенного выше примера входные данные будут выглядеть так (сохранены как input.txt и переданы в качестве аргумента основному сценарию):

MyProgram.exe
MyProgram.exe.config
MyProgram.pdb
.\XmlConfig\*.xml

Я бы предпочел подход с использованием подстановочных знаков, поскольку не многие люди знают регулярное выражение.


person Neolisk    schedule 04.02.2013    source источник


Ответы (2)


я не знаю, что не так с фильтром, но вы все равно можете сделать

$files | % { copy-item ..\bin\release\$_ -Destination .\test}

если вы хотите сохранить структуру каталогов, вам придется немного ослабить это, например:

$sourcedir="c:\temp\test"
$f=@("existing.txt","hf.csv";"..\dir2\*.txt")
$f |%{
     $source=ls (join-Path $sourcedir $_) |select -expand directoryname    
     if ("$source" -like "$sourcedir*"){
        $destination=$source.Substring($sourcedir.Length)+".\" 
     }
     else{
        $destination=$_
     }  
    copy-item $sourcedir\$_ -Destination $destination -WhatIf
}
person Loïc MICHEL    schedule 04.02.2013
comment
-Фильтр принимает только одну строку - person Stanley De Boer; 04.02.2013
comment
Мне нужно быть в целевой папке, чтобы это работало. Но если я нахожусь в целевой папке, ..\bin\release не сработает. Или $files нужно указать абсолютный путь, который мне не нужен. - person Neolisk; 04.02.2013
comment
вот как вы это сделали в своем примере... Относительный путь и подстановочные знаки тоже работают с моим кодом - person Loïc MICHEL; 04.02.2013
comment
Если я оставлю ваш код КАК ЕСТЬ, он создаст файл размером с папку, поэтому кажется, что все содержимое добавляется в один файл. Если я добавлю завершающую обратную косую черту .\test\ , будет отображаться эта ошибка для каждого копируемого файла: Copy-Item : The filename, directory name, or volume label syntax is incorrect. Я попытался заключить соответствующие части в двойные кавычки - тот же результат. - person Neolisk; 04.02.2013
comment
Каким-то образом я почти заставил его работать как часть производственного сценария, хотя в тесте он не работал. Единственная проблема в том, что он не сохраняет структуру папок, поэтому все файлы оказываются в одной папке, в том числе и из .\XmlConfig\ . Я попробовал флаг -Container, который должен сохранять структуру папок, но это не дало никакого эффекта. - person Neolisk; 04.02.2013

AFAICT -Include работает только с именами файлов или именами каталогов, а не с комбинациями, т.е. с путями. Вы можете попробовать что-то вроде этого:

$files = 'MyProgram\.exe|MyProgram\.exe\.config|MyProgram\.pdb|XmlConfig\\.*?\.xml'

Get-ChildItem ..\bin\release -r | Where {!$_.PSIsContainer -and ($_.FullName -match $files)} | 
    Copy-Item -Dest .\test

С подстановочными знаками вы можете сделать это следующим образом:

$files = @('*MyProgram.exe','*MyProgram.exe.config','*MyProgram.pdb','*\XmkConfig\*.xml')
Get-ChildItem ..\bin\release -r |
    Foreach {$fn=$_.Fullname;$_} | 
    Where {!$_.PSIsContainer -and ($files | Where {$fn -like $_})} | 
    Copy-Item -Dest .\test    
person Keith Hill    schedule 04.02.2013
comment
Есть ли способ иметь общую реализацию, которая принимает массив строк? Первоначально я думал поместить все необходимые файлы/пути в строку здесь (которая может быть разделена новой строкой, чтобы соответствовать этой концепции массива строк) или даже в отдельный файл для удобства редактирования, чтобы не- Знающий Powershell человек может понять и изменить его по мере необходимости. - person Neolisk; 04.02.2013
comment
Конечно, это легко. Другая проблема заключается в том, хотите ли вы придерживаться шаблонов регулярных выражений или более ограниченных шаблонов подстановочных знаков? Если у вас все в порядке с регулярным выражением, поместите каждый шаблон в строку в файле и воссоздайте $files следующим образом: $OFS="|"; $files = "$(get-content files.txt)". Примечание: этот конкретный подход не допускает пустых строк в любом месте файла. - person Keith Hill; 04.02.2013
comment
Я бы предпочел подстановочные знаки, не многие люди знают регулярное выражение. Кроме того, выражения не должны быть настолько сложными, чтобы когда-либо нуждаться в регулярных выражениях. Я могу убедиться, что входной файл следует определенному форматированию, если его легко поддерживать. Не могли бы вы привести пример подстановочных знаков? - person Neolisk; 04.02.2013
comment
@KeithHill вы имели в виду $EOF? - person Loïc MICHEL; 05.02.2013
comment
С подстановочными знаками вам нужно будет изменить логику сопоставления. Я обновлю ответ здесь в ближайшее время. @Kayasax, нет, я имел в виду $OFS (разделитель полей вывода). - person Keith Hill; 05.02.2013
comment
Спасибо за обновление, та же проблема с ним - *\XmlConfig\*.xml теряет структуру папок, поэтому все файлы просто оказываются плоскими в папке .\test. Это нормально? - person Neolisk; 05.02.2013
comment
Да, если вы копируете файлы, копируются только файлы, а не структура папок. Если вы копируете папки, структура папок сохраняется с помощью -Recurse. - person Keith Hill; 05.02.2013