Перемикач XCOPY для створення вказаного каталогу, якщо він не існує?


78

Я використовую XCOPY у події після збірки, щоб скопіювати скомпільовані бібліотеки DLL із вихідних папок у основну вихідну папку програми. Бібліотеки DLL копіюються в підпапку "Модулі" в головній папці виводу програми, наприклад:

xcopy  "$(TargetPath)" "$(SolutionDir)Prism4Demo.Shell\$(OutDir)Modules\" 

Команда працює нормально, якщо папка Модулі існує, але під час тестування я виявив, що якщо папка не існує, XCOPY її не створює, і команда не працює.

Чи є перемикач XCOPY, який призведе до створення папки, якщо вона не існує? Якщо ні, що б я додав до своєї події після збірки для створення папки, якщо вона не існує? Спасибі за вашу допомогу.


Дивіться мій коментар до прийнятої відповіді
Девід Вінеман,

Відповіді:


54

Я спробував це в командному рядку за допомогою

D:\>xcopy myfile.dat xcopytest\test\

і цільовий каталог був правильно створений.

Якщо ні, ви можете створити цільовий каталог за допомогою mkdirкоманди з cmdувімкненими розширеннями команд, наприклад

cmd /x /c mkdir "$(SolutionDir)Prism4Demo.Shell\$(OutDir)Modules\"

('/ x' включає розширення команд, якщо вони не ввімкнені за замовчуванням у вашій системі, я не настільки знайомий з ними cmd)

використання

cmd /? 
mkdir /?
xcopy /?

для подальшої інформації :)


13
Я прийняв цю відповідь, оскільки перша частина виявилася правильною. XCOPY буде створити каталог, якщо він вже не існує. Я виявив, що Windows намагається попросити підтвердження перезапису на мою команду XCOPY. VS цього не дозволяє, тому він вийшов із кодом 2. Я додав параметр / y, який звучить підказку, і команда працює. Перевірено шляхом очищення розчину та видалення папки, а потім відновлення. Папку створив XCOPY.
Девід Вінеман

@DavidVeeneman Це не працює у VS2015 під Windows 10; помилки xcopy із повідомленням "помилка: недійсний шлях". Так що ні. xcopy не (завжди) створюватиме каталог призначення
Tom Lint

3
XCOPY справді створює каталог, але він буде робити це, лише якщо немає однозначності: Це неоднозначно: D: \> xcopy myfile.dat xcopytest \ test Це не: D: \> xcopy myfile.dat xcopytest \ test \ ( зверніть увагу на останнє '\')
azog

120

Відповідь на використання "/ I" працює, але з невеликою хитрістю - у цілі ви повинні закінчити символом \, щоб сказати xcopy, що ціль - це каталог, а не файл!

Приклад:

xcopy "$(TargetDir)$(TargetName).dll" "$(SolutionDir)_DropFolder" /F /R /Y /I

не працює і повертає код 2, але цей:

xcopy "$(TargetDir)$(TargetName).dll" "$(SolutionDir)_DropFolder\" /F /R /Y /I

Аргументи командного рядка, використані в моєму зразку:

/ F - Відображає повні імена вихідних та цільових файлів

/ R - Це перезапише файли лише для читання

/ Y - придушує запит на перезапис існуючих файлів

/ I - Припускає, що призначення є каталогом (але має закінчуватися на \)


4
Відповідь повинна бути кориснішою, якщо вона була детально розроблена, навіщо використовувати /F, чому /R, чому /Y. У моєму випадку /Yпроблема вирішена, і майбутнім читачам було б корисно знати, чому без видобутку даних в Інтернеті.
Імператор Оріоній,

Що робити, якщо мені потрібно створити два каталоги? Чи може xcopy це зробити для мене?
Pedro77

3
У моєму випадку /Iне потрібно для умовного створення каталогу, а +1 для закінчення шляху зворотною косою рисою.
Кент Вайгель,

15

Я ненавиджу крок PostBuild, він дозволяє занадто багато речей відбуватись поза сферою дії інструмента побудови. Я вважаю, що краще дозволити MSBuild керувати процесом копіювання та виконувати оновлення. Ви можете відредагувати файл .csproj таким чином:

  <Target Name="AfterBuild" Inputs="$(TargetPath)\**">
    <Copy SourceFiles="$(TargetPath)\**" DestinationFiles="$(SolutionDir)Prism4Demo.Shell\$(OutDir)Modules\**" OverwriteReadOnlyFiles="true"></Copy>
  </Target>

1
Я думаю, що ваші входи, файли джерел та файли призначення не правильні. Він копіює DDL в папку модулів, а не навпаки.
Fun Mun Pieng

Я б все одно додав їх до групи властивостей.
Річ Мелтон,

1
Введення = "..." слід видалити. У VS 2012 я отримую помилку про те, що "ціль" AfterBuild "відсутня в специфікації виводу. Якщо ціль оголошує вхідні дані, вона також повинна оголошувати виходи".
angularsen

$ (TargetPath) - це шлях до вихідного файлу .DLL, тому, ймовірно, також слід видалити \ ** зі значення SourceFiles.
angularsen

Якщо ви видалите входи = "", ви втратите відстеження збірки. Це дворічне питання, якщо ви хочете оновити його, сміливо.
Річ Мелтон,

15

Використовуйте / i з xcopy, і якщо каталог не існує, він створить каталог для вас.


6

Ви можете скористатися робокопією:

robocopy "$(TargetPath)" "$(SolutionDir)Prism4Demo.Shell\$(OutDir)Modules" /E

+1: Я не знав про команду robocopy, доступну у Vista та Win7. Дякую. Не думайте, що тут це спрацює. Я копіюю файл, а не папку.
Девід Вінеман

Я теж не знав про робокопію. Корисно знати, але, на жаль, це не вдається із повідомленням "Доступ заборонено" при копіюванні в папку під Файлами програм. (xcopy не має з цим проблем.)
Том Богле

Після подальшого вивчення схоже на те, що xcopy може із задоволенням скопіювати нові файли в існуючі папки в розділі Program Files, але, очевидно, він також не може створювати нові папки (без доступу адміністратора).
Том Богле

1

Я спробував це за командою. Це працює на мене.

if "$(OutDir)"=="bin\Debug\"  goto Visual
:TFSBuild
goto exit
:Visual
xcopy /y "$(TargetPath)$(TargetName).dll" "$(ProjectDir)..\Demo"
xcopy /y "$(TargetDir)$(TargetName).pdb" "$(ProjectDir)..\Demo"
goto exit
:exit

1

Проста коротка відповідь така:

xcopy /Y /I "$(SolutionDir)<my-src-path>" "$(SolutionDir)<my-dst-path>\"

0

Спробуйте / Е

Щоб отримати повний перелік опцій: xcopy /?


Дякуємо, але / e - за копіювання існуючої структури підкаталогу у джерелі. Я копіюю файл у кореневому коді джерела в новий підкаталог призначення.
Девід Вінеман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.