none
Copy Files In txt file and rename the path to keep folder structure RRS feed

  • Question

  • I have to copy files that are listed in a txt file to another directory but keep the remaining folder structure in tact.

    Example list in txt file:

    C:\files\prod\Folder1\1\2\3\4\5\something.pdf
    C:\files\prod\Folder10\11\12\13\14\15\another.pdf

    Need to move them to another location (D:\) example here.  I need to keep everything after prod d:\copied\files\prod.

    D:\copied\files\prod\thesamefolderstructure.

    I have a function for removing the lead:

    function Remove-LeadingString
    {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
            [AllowEmptyString()]
            [string[]]
            $String,

            [Parameter(Mandatory = $true)]
            [string]
            $LeadingString
        )

        process
        {
            foreach ($s in $String)
            {
                if ($s.StartsWith($LeadingString, $true, [System.Globalization.CultureInfo]::InvariantCulture))
                {
                    $s.Substring($LeadingString.Length)
                }
                else
                {
                    $s
                }
            }
        }
    }

    $Files = cat C:\Source\logs\files.txt

    $Folders = ($Files | Remove-LeadingString -LeadingString 'D:\files\prod')

    $News = ForEach($Folder in $Folders){
      Join-Path 'D:\Copied' -ChildPath $Folder
        ForEach($New in $News){
      Copy-item $Files -Destination $new -WhatIf
    }}

    This created everfile for each parent path.  Thnks


    LJF3RD

    Saturday, June 24, 2017 10:28 AM

Answers

  • This should be:

    $destination = Join-Path $targetroot + $filepath

    this:

    $destination = Join-Path $targetroot $filepath

    No plus sign.

    Get-Item (Get-Content files.txt) |
    	ForEach-Object{
    		# $_ is the file name so:
    		$filepath = $_ -replace 'C:'
    		$destination = Join-Path $targetroot $filepath
    		$destination = Split-Path $destination
    		New-Item $destination -Force
    		Copy-Item $_.FullName $destination
    	}

    Plus we needed to remove the filename.


    \_(ツ)_/

    • Marked as answer by ljfiii Tuesday, June 27, 2017 3:26 PM
    Tuesday, June 27, 2017 2:20 PM

All replies

  • Don't forget to ask your question.

    -- Bill Stewart [Bill_Stewart]

    Saturday, June 24, 2017 6:16 PM
    Moderator
  • Was my post not clear?  I state my question in the begining.  I need to copy files that are listed in a text folder and keep the folder structure. 

    From

    D:\files\prod\the\rest\of\the\file\path\file.txt

    to

    D:\Destination\files\prod\the\rest\of\the\file\path\file.txt

    I need to copy or rename the beginning of the file path.  My script is appending every file to each path.  So 5 files 5 paths i get 25 files.  Please help.


    LJF3RD

    Saturday, June 24, 2017 10:40 PM
  • What is the issue or error?  Just posting a script and saying you need something different is not a scripting question.

    To create a folder structure use "New-Item" with a complete path.  You will have to extract the part of the path that you want to create and modify it with the new root.

    Of course there are a number of other ways to accomplish this. Create your script and post back with specific questions.

    You should also look at RoboCopy as it can do this assuming the source files are arranged correctly.


    \_(ツ)_/

    Saturday, June 24, 2017 10:57 PM
  • Ok the first thing i did was robocopy "d:\files\prod" "D:\Replica\files\prod" /MIR -  this is so I am starting with the complete duplicate so the original is in tact.  Then I am using the function (Remove-LeadingString -LeadingString 'D:\files\prod') above so I can split the path of each file path in the file file.txt (D:\files\prod\Folder1\1\2\3\4\5\something.pdf turns into D:\Replica\files\prod\Folder1\1\2\3\4\5\something.pdf it does this for the 5 lines in the text file). When I try to run the following I get a mismatch file paths and each file in all of the end folders.

    $Files = cat C:\Source\logs\files.txt  < --- reads 5 files with the full path

    $Folders = ($Files | Remove-LeadingString -LeadingString 'D:\files\prod') <-- Renames each file path

    $News = ForEach($Folder in $Folders){
      Join-Path 'D:\Copied' -ChildPath $Folder  <---- each file gets the new root appended to rest of the split-path
        ForEach($New in $News){
      Copy-item $Files -Destination $new -WhatIf < --- In here its mismatch file paths and extra files.
    }}


    LJF3RD

    Sunday, June 25, 2017 3:08 AM
  • Why?  Just get the filenames from the file

    Get-Item (Get-Content files.txt) |
          ForEach-Object{
               # $_ is the file name so:
               $filepath = $_ -replace 'C:'
               $destination = Join-Path $targetroot + $filepath
               New-Item $destination -Force
               Copy-Item $_ $destination
          }
    
    That is all you have to do.  Don't overcomplicate the task.


    \_(ツ)_/

    Sunday, June 25, 2017 3:47 AM
  • Thank you for your help.  I do tend to make it more complex than it needs to be.  With that said I am getting some errors and the Join-Path looks right until it does the copy.  then it takes just the file name and not the folder structure.  It does copy the files but puts them in my current working directory (D:\CloudSupport\Final) but does not create the folder structure. Any help is greatly appreciated.

    Join-Path : A positional parameter cannot be found that accepts argument '\CloudSupport\prod\57\192\9939\9939\7494\FW  PO 21135   - OS&D #0022 - DAMAGED HEAT EXCHANGERS.msg'.
    At line:7 char:36
    +            $destination = Join-Path <<<<  -Path $targetroot + $filepath
        + CategoryInfo          : InvalidArgument: (:) [Join-Path], ParameterBindingException
        + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.JoinPathCommand

    New-Item : Cannot bind argument to parameter 'Path' because it is null.
    At line:8 char:20
    +            New-Item <<<<  $destination -Force
        + CategoryInfo          : InvalidData: (:) [New-Item], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.NewItemCommand

    What if: Performing operation "Copy File" on Target "Item: D:\CloudSupport\prod\57\192\9939\9939\7494\FW  PO 21135   - OS&D #0022 - DAMAGED HEAT EXCHANGERS.msg Destination: D:\CloudSupport\Final\FW  PO 21135   - OS&D #0022 - DAMAGED HEAT EXCHANGERS.msg".

      

    LJF3RD

    Tuesday, June 27, 2017 2:13 PM
  • This should be:

    $destination = Join-Path $targetroot + $filepath

    this:

    $destination = Join-Path $targetroot $filepath

    No plus sign.

    Get-Item (Get-Content files.txt) |
    	ForEach-Object{
    		# $_ is the file name so:
    		$filepath = $_ -replace 'C:'
    		$destination = Join-Path $targetroot $filepath
    		$destination = Split-Path $destination
    		New-Item $destination -Force
    		Copy-Item $_.FullName $destination
    	}

    Plus we needed to remove the filename.


    \_(ツ)_/

    • Marked as answer by ljfiii Tuesday, June 27, 2017 3:26 PM
    Tuesday, June 27, 2017 2:20 PM
  • New-Item needed -ItemType Directory but it looks good.  Thanks!!!

    LJF3RD

    Tuesday, June 27, 2017 3:26 PM