Tengo una serie de archivos dentro de una carpeta. Todos ellos tienen un nombre que coincida con el patrón DR__.*. Quiero copiar a otra carpeta, pero quitando el DR.__ prefijo. ¿Cómo puedo hacer esto con MSBuild? Yo solía hacer esto de esta manera el uso de NAnt:

<mkdir dir="${ClientPath + '\bin\' + ConfigurationName + '\Parameters'}"/>
<foreach item="File" property="Filename" in="CVParameters">
    <if test="${string::contains(Filename, Client + '_')}">
        <property name="newFilename" value="${ string::substring( Filename, string::last-index-of(Filename, '__') + 2, string::get-length(Filename) - string::last-index-of(Filename, '__') - 2) }"/>
        <copy file="${ Filename  }" tofile="${ ClientPath + '\bin\' + ConfigurationName + '\Parameters\' + newFilename }" overwrite="true"/>
    </if>
</foreach>

OriginalEl autor dario_ramos | 2011-03-21

4 Comentarios

  1. 14

    Estoy de acuerdo con @Si la solución. Pero con MSBuild 4.0 usted puede hacerlo con el construido en la funcionalidad. NAnt secuencia de comandos es mucho más clara que la mía. Pero voy a agregar como una solución sólo para mostrar MSBuild 4.0 técnicas:

        <ItemGroup>
           <CVParameters Include="$(YourBaseDir)\**\DR__*" />
        </ItemGroup>
    
        <Target Name="CopyAndRename" 
                Condition="'@(CVParameters)'!=''"
                Outputs="%(CVParameters.Identity)">
             <PropertyGroup>
                <OriginalFileName>%(CVParameters.FileName)%(CVParameters.Extension)</OriginalFileName>          
                <Prefix>DR__</Prefix>
                <PrefixLength>$(Prefix.Length)</PrefixLength>
                <OriginalFileNameLength>$(OriginalFileName.Length)</OriginalFileNameLength>
                <SubstringLength>$([MSBuild]::Subtract($(OriginalFileNameLength),$(PrefixLength)))</SubstringLength>
                <ModifiedFileName>$(OriginalFileName.Substring($(PrefixLength),$(SubstringLength)))</ModifiedFileName>
                <DestinationFullPath>$([System.IO.Path]::Combine($(DestinationDir),$(ModifiedFileName)))</DestinationFullPath>
             </PropertyGroup>                                                                                                                                         
    
             <Copy SourceFiles="%(CVParameters.FullPath)" 
                   DestinationFiles="@(DestinationFullPath)" 
                   SkipUnchangedFiles="true" />
        </Target>

    Editar (OP): Para obtener este trabajo, he tenido que cambiar de $(DestinationFullPath)en Copy con @(DestinationFullPath), para que coincida con el número de Archivos de Origen y Destino. También, he tenido que cambiar el prefijo a DR__, desde DR__. no iba a funcionar.

    Esta respuesta es más sencillo, me puso sobre la pista de la derecha y me dio una sensación de MSBuild técnicas. Gracias!
    No puedo entender cómo llamar a ese destino desde el exterior..

    OriginalEl autor Sergio Rykov

  2. 10

    Recientemente he tenido que resolver la tarea similar y me hizo uso del Elemento de metadatos.
    Las ventajas de esta solución son:

    1. Pequeño script de compilación de tamaño.
    2. Utilizando el estándar del Sistema.Funciones de cadena para conseguir modificado el nombre.
    3. De metadatos personalizados es la copia de la definición de nuevos elementos, que a base de elementos ya existentes (por ejemplo, Elementos <TempItemsBak Include="@(TempItems-> ... CustomTransform ... )"> obtendrá original del elemento de metadatos de valores, por lo que usted puede utilizar para su posterior procesamiento)

    <Project DefaultTargets="CopyNoPrefix" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

      <PropertyGroup>
        <InputDir Condition="'$(InputDir)' == '' ">.</InputDir>
        <OutputDir Condition="'$(OutputDir)' == '' ">Output</OutputDir>
      </PropertyGroup>
    
      <ItemGroup>
        <CVParameters Include="$(InputDir)\**\DR__.*" />
      </ItemGroup>
    
      <Target Name="CopyNoPrefix">
        <ItemGroup>
          <!-- Items with new name. Use System.String's Remove method to get full file name without prefix -->
          <!-- http://msdn.microsoft.com/en-us/library/vstudio/ee886422(v=vs.100).aspx -->
          <TempItems Include="@(CVParameters->'%(Filename)%(Extension)'->Remove(0, 5))">
            <!-- Define metadata based on original item for next step -->
            <OriginalPath>%(Identity)</OriginalPath>
            <SavedRecursiveDir>%(RecursiveDir)</SavedRecursiveDir>
          </TempItems>
        </ItemGroup>
    
        <!-- Use new items along with their metadata for copying -->
        <Copy SourceFiles="@(TempItems->'%(OriginalPath)')" DestinationFiles="@(TempItems->'$(OutputDir)\%(SavedRecursiveDir)%(Identity)')" />
      </Target>
    
    </Project>

    OriginalEl autor Ivan Samygin

  3. 2

    Se puede utilizar MSBuild 4.0? Si es así, entonces se refieren a este respuesta (y Ayuda de MSDN). De lo contrario, la RegexReplace tarea en MSBuildCommunityTasks también debe trabajar, a costa de tener que soportar una herramienta externa (para ir de MSBuild 4.0 si es posible).

    Otro (no probado) es la opción TextString tarea en MSBuildExtensionPack.

    A falta de esos, del rollo de su propia tarea?

    La Documentación de MSDN sobre MSBuild es una falta de bit, por lo que Sergio respuesta fue más útil. Pero yo no había visto las cosas acerca de las Funciones de Propiedad, así que gracias a ti también.
    No hay problemas de Darío, estoy de acuerdo Sergio, fue la respuesta de útil! +1 me 2 🙂

    OriginalEl autor si618

  4. 2

    Hace poco he tenido que hacer algo similar a esto, y terminó con un chapucero, pero solución viable basado en la línea de tareas personalizadas.

        <UsingTask TaskName="GetNewFileName" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
    <OriginalFile ParameterType="System.String" Required="true" />
    <PackageVersion ParameterType="System.String" Required="true" />
    <NewFile Output="true" />
    </ParameterGroup>
    <Task>
    <Code Type="Fragment" Language="cs">
    <![CDATA[
    int versionIndex = OriginalFile.IndexOf(PackageVersion);
    versionIndex = versionIndex < 0 ? OriginalFile.Length : versionIndex;
    NewFile = OriginalFile.Substring(0,versionIndex) + "nupkg";
    ]]>
    </Code>
    </Task>
    </UsingTask>
    <UsingTask TaskName="Combine" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
    <Path ParameterType="System.String" Required="true" />
    <File ParameterType="System.String" Required="true" />
    <FullPath Output="true" />
    </ParameterGroup>
    <Task>
    <Code Type="Fragment" Language="cs">
    <![CDATA[
    FullPath = System.IO.Path.Combine(Path, File);
    ]]>
    </Code>
    </Task>
    </UsingTask>
    <Target Name="AfterCompile" Condition="'$(IsDesktopBuild)'!='true'">
    <ItemGroup>
    <Nuspecs Include="$(SolutionRoot)\$(WorkingBranch)\Nuspec\**\*.nuspec"/>
    </ItemGroup>
    <!-- Build nugets -->
    <Message Text="DEBUG: Build nuget packages" />
    <Exec
    WorkingDirectory="$(NuspecsPath)"
    Condition=""
    Command='$(NugetPath) pack "%(Nuspecs.FullPath)" -Version 1.0.0.$(PackageVersion)' />
    <ItemGroup>
    <Nupkgs2 Include="$(NuspecsPath)\**\*.nupkg"/>
    </ItemGroup>
    <GetNewFileName OriginalFile="%(Nupkgs2.FileName)%(Nupkgs2.Extension)" PackageVersion="$(PackageVersion)">
    <Output ItemName="RenamedNuPkgs" TaskParameter="NewFile"/>
    </GetNewFileName>
    <Combine File="%(RenamedNuPkgs.Filename)%(RenamedNuPkgs.Extension)" Path="$(NugetRepository)">
    <Output ItemName="PackagesRepository" TaskParameter="FullPath"/>
    </Combine>
    <Message Text="Renamed nuget packages: @(RenamedNuPkgs)"/>
    <Message Text="Repository Renamed nuget packages: @(PackagesRepository)"/>
    <Copy SourceFiles="@(Nupkgs2)" DestinationFiles="@(PackagesRepository)"/>
    +1: yo no sabía acerca de esta alternativa. Gracias por compartir!

    OriginalEl autor Craig Vermeer

Dejar respuesta

Please enter your comment!
Please enter your name here