91 votes

Le commutateur XCOPY pour créer le répertoire spécifié s'il n'existe pas ?

J'utilise XCOPY dans un événement post-construction pour copier les DLL compilées de leurs dossiers de sortie vers le dossier de sortie de l'application principale. Les DLL sont copiées dans un sous-dossier "Modules" du dossier de sortie de l'application principale, comme ceci :

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

La commande fonctionne bien si le dossier Modules existe, mais j'ai découvert lors des tests que si le dossier n'existe pas, XCOPY ne le crée pas et la commande échoue.

Existe-t-il un commutateur XCOPY qui fera en sorte que le dossier soit créé s'il n'existe pas ? Sinon, que dois-je ajouter à mon événement post-construction pour créer le dossier s'il n'existe pas ? Merci pour votre aide.

0 votes

Voir mon commentaire à la réponse acceptée

132voto

psulek Points 984

La réponse à l'utilisation de "/I" fonctionne mais avec une petite astuce - dans la cible vous devez terminer avec le caractère \ pour dire à xcopy que la cible est un répertoire et non un fichier !

Exemple :

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

ne fonctionne pas et renvoie le code 2, mais celui-ci :

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

Arguments de ligne de commande utilisés dans mon échantillon :

/F - Affiche les noms complets des fichiers source et cible

/R - Ceci va écraser les fichiers en lecture seule.

/Y - Supprime la demande d'écraser un ou plusieurs fichiers existants

/I - Suppose que la destination est un répertoire (mais doit se terminer par \)

4 votes

La réponse serait plus utile si elle était élaborée pourquoi utiliser /F Pourquoi ? /R Pourquoi ? /Y . Dans mon cas /Y a résolu le problème et les futurs lecteurs gagneraient à savoir pourquoi sans avoir à fouiller les données sur Internet.

0 votes

Que faire si je dois mettre en caisse deux répertoires ? Est-ce que xcopy peut le faire pour moi ?

3 votes

Dans mon cas, /I n'était pas nécessaire pour créer conditionnellement le répertoire, mais +1 pour terminer le chemin avec backslash.

60voto

MartinStettner Points 14514

J'ai essayé de le faire en ligne de commande en utilisant

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

et le répertoire cible a été correctement créé.

Si ce n'est pas le cas, vous pouvez créer le répertoire cible en utilisant la commande mkdir avec cmd Les extensions de commande de l'utilisateur sont activées comme

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

('/x' active les extensions de commande au cas où elles ne sont pas activées par défaut sur votre système, je ne suis pas très familier avec cmd )

utiliser

cmd /? 
mkdir /?
xcopy /?

pour plus d'informations :)

13 votes

J'ai accepté cette réponse car la première partie s'est avérée correcte. XCOPY00 sera créer le répertoire, s'il n'existe pas déjà. J'ai découvert que Windows essayait de demander une confirmation d'écrasement sur ma commande XCOPY. VS ne le permet pas, donc il s'est arrêté avec le code 2. J'ai ajouté le paramètre /y, qui supprime l'invite, et la commande fonctionne. J'ai testé en nettoyant la solution et en supprimant le dossier, puis en le reconstruisant. Le dossier a été créé par XCOPY.

0 votes

@DavidVeeneman Cela ne fonctionne pas dans VS2015 sous Windows 10 ; xcopy se bloque avec le message "error : Invalid path". Donc non, xcopy ne sera pas (toujours) créer le répertoire de destination

4 votes

XCOPY crée bien le répertoire, mais il ne le fera que s'il n'y a pas d'ambiguïté : Ceci est ambigu : D:\>xcopy monfichier.dat xcopytest \test Ce n'est pas le cas : D:\>xcopy myfile.dat xcopytest \test\ (notez le dernier "\")

15voto

Ritch Melton Points 7173

Je déteste l'étape PostBuild, elle permet à trop de choses de se produire en dehors du champ d'action de l'outil de construction. Je pense qu'il est préférable de laisser MSBuild gérer le processus de copie, et faire la mise à jour. Vous pouvez éditer le fichier .csproj comme ceci :

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

1 votes

Je pense que vos Inputs, SourceFiles et DestinationFiles ne sont pas corrects. Il est en train de copier la DDL dans le dossier des modules, et non l'inverse.

0 votes

Je les ajouterais de toute façon à un groupe de propriétés.

1 votes

Inputs="..." doit être supprimé. Dans VS 2012, je reçois une erreur selon laquelle "La cible "AfterBuild" n'a pas de spécification de sortie. Si une cible déclare des entrées, elle doit également déclarer des sorties."

15voto

GeekyGuy Points 61

Utilisez le /i avec xcopy et si le répertoire n'existe pas, il le créera pour vous. pour vous.

6voto

John Simons Points 3053

Vous pourriez utiliser robocopy :

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

0 votes

+1 : Je ne connaissais pas la commande robocopy disponible dans Vista et Win7. Merci. Je ne pense pas que cela fonctionnera ici, cependant. Je suis en train de copier un fichier, plutôt qu'un dossier.

0 votes

Je ne connaissais pas non plus la robocopie. Bon à savoir, mais malheureusement, il échoue avec le message "Access is denied" si on copie dans un dossier sous Program Files. (xcopy n'a pas de problème avec ça).

0 votes

Après une étude plus approfondie, il semble que xcopy puisse se contenter de copier de nouveaux fichiers dans des dossiers existants sous Program Files, mais il ne peut apparemment pas non plus créer de nouveaux dossiers (sans accès administrateur).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X