locked
Copy, count files, test path, process indicator and System.IO.FileInfo RRS feed

  • Question

  • I found this, sctipt, that I try to re-write.

    As it is, it creates sub folders in the targetfolder, which I found out how to stop it from, by deleting the "\" backslash sign in line 9.

    But what I also want is that subfolders if such should exist, also gets copied from $source to $target folder, as of now this doesn't happen. Reason why I chose to try to re-write the script is basically, I can read what it does and I like all the flashy Things like counting and that it shows the percentage of the processbar AND the processbar :).

    I just don't now how to re-write it proberly. By the way nothing should be re-named in the targetfolder every thing from sourcefolder should be "as is" in the sourcefolder.

    $SourceFolder = "C:\Color1\TRID"
    $targetFolder = “C:\Color2\TRID”
    $numFiles = (Get-ChildItem -Path $SourceFolder -Filter *.*).Count
    $i=0
    clear-host;
    Write-Host ‘This script will copy ‘ $numFiles ‘ files from ‘ $SourceFolder ‘ to ‘ $targetFolder
    Read-host -prompt ‘Press enter to start copying the files’
    Get-ChildItem -Path $SourceFolder -Filter *.* | %{ 
       [System.IO.FileInfo]$destination = (Join-Path -Path $targetFolder -ChildPath $_.Name.replace(“_”,“\”))  
       
       if(!(Test-Path -Path $destination.Directory ))
     { 
     New-item -Path $destination.Directory.FullName -ItemType Directory 
     } 
     
     [int]$percent = $i / $numFiles * 100 
        
        copy-item -Path $_.FullName -Destination $Destination.FullName
        write-Progress -Activity “Copying … ($percent %)” -status $_  -PercentComplete $percent -verbose
    $i++
    }
    Write-Host ‘Total number of files read from directory ‘$SourceFolder ‘ is ‘ $numFiles
    Write-Host ‘Total number of files that was copied to ‘$targetFolder ‘ is ‘ $i
    Read-host -prompt “Press enter to complete…”
    clear-host;


    • Edited by SILB Monday, February 23, 2015 2:11 PM
    Monday, February 23, 2015 2:10 PM

Answers

  • Robocopy can meet all of your requirements. Just type the robocopy command, followed by the parameters you want, and press Enter. It runs just fine in PowerShell. I have used it for years this way without problems.

    Robocopy documentation is readily available by a quick search.

    http://www.bing.com/search?q=robocopy documentation


    -- Bill Stewart [Bill_Stewart]

    • Proposed as answer by Bill_Stewart Tuesday, March 3, 2015 3:09 PM
    • Marked as answer by Bill_Stewart Friday, April 10, 2015 3:35 PM
    Friday, February 27, 2015 3:43 PM

All replies

  • 1) I don't think there's a way for us to guess what you want to do based solely on the information in your post.

    2) This forum is for specific scripting questions and isn't really the place to ask others to rewrite a script for you.

    3) Generally robocopy is the best solution for file replication tasks.


    -- Bill Stewart [Bill_Stewart]

    Monday, February 23, 2015 5:14 PM
  • I understand what you are saying, so I gave it another shot. Now I've tried to re-write as much of it as I could and only need some help to the last bit.

    I have a targetfolder called Color2\TRID and a sourcefolder called Color1\TRID1

    When I run the script now it does not only copy the subfolders that exist in the sourcefolder, it does also under the targetfolders folder called TRID, create extra subfolders, which it should not do. Here is the script I re-wrote:

    $SourceFolder = "C:\Color1\TRID"
    $targetFolder = “C:\Color2\TRID”
    $numFiles = (Get-ChildItem -Path $SourceFolder -Filter *.*).Count
    $i=0
    Write-Host ‘This script will copy ‘ $numFiles ‘ files from ‘ $SourceFolder ‘ to ‘ $targetFolder
    Read-host -prompt ‘Press enter to start copying the files’
    Get-ChildItem -Path $SourceFolder -Filter *.* | %{
     [int]$percent = $i / $numFiles * 100 
        
        copy-item $sourcefolder -Destination $targetfolder -Recurse -Force
        write-Progress -Activity “Copying … ($percent %)” -status $_ -PercentComplete $percent -verbose
    $i++
    }
    Write-Host ‘Total number of files read from directory ‘$SourceFolder ‘ is ‘ $numFiles
    Write-Host ‘Total number of files that was copied to ‘$targetFolder ‘ is ‘ $i
    Read-host -prompt “Press enter to complete…”

    Tuesday, February 24, 2015 10:27 AM
  • Sorry, but I still don't understand what you are trying to do. Your post does not give enough information.

    Again, I would recommend using robocopy instead of trying to script it yourself. It has a host of features that are designed for robust file copying. This isn't a support forum for robocopy, though.


    -- Bill Stewart [Bill_Stewart]

    Tuesday, February 24, 2015 1:32 PM
  • @Bill

    Have you tried to test my script? If you did, you would understand the problem

    Second: I don't care much for robocopy, since it has never aid me for my copy quests.

    Third: you might not understand it, but I hope somebody else does, and that this person acutally tries the script, in order to verify my problem.

    if {Forum not -eq robocopy -then "DON'T BRING IT UP"}

    Tuesday, February 24, 2015 1:52 PM
  • I have not tried to test the script; sorry, but this is because I don't have the time to reproduce your environment (not sure how possible that would be anyway, based only on what you have posted) or to debug your code for you.

    What I recommend is to post exact and specific instructions to recreate a minimal test environment. For example, "create these directories and files." Then post a very short script that contains only the absolute minimum amount of code needed to reproduce the problem.

    The basic principle is this: If you want free help, then you need to make it as easy as possible, instead of dumping your code, expecting someone figure out what it's supposed to do, and then fix it for you.


    -- Bill Stewart [Bill_Stewart]

    Tuesday, February 24, 2015 3:25 PM
  • !Test-setup as requested:

    I want to copy files and subfolders (No use of robocopy), from C:\test-1\testfolder to C:\test-2\testfolder

    The process must includes subfolders, and show Progress in percent, and with a status bar including the number of files that will be copied.

    I does also think it would be cool with a Read-Host -prompt saying, "press Enter to continue".

    Here is the most basic of my script.

    $SourceFolder = "C:\Color1\TRID"
    $targetFolder = “C:\Color2\TRID”
    #Count files that will be copied...How?
    Read-Host -Prompt 'Press Enter to Start Copying...'
    Copy-Item $SourceFolder -Recurse -Destination $targetFolder -Force -verbose
    #Show percentage, status bar, and number of files being copied... How?

    I've solved one of my puzzles, and that is, why I'd always got an extra subfolder with the same name as the parent folder in test-directory 2. Now I just need a bit of help with the fun part. And that is to put on the flashy Things like status bar, percentages and file-counting from source to target folder. I hope you will help me with this bit. :)




    • Edited by SILB Wednesday, February 25, 2015 8:11 AM
    Wednesday, February 25, 2015 7:36 AM
  • Since you are copying all files regardless if they exist in the destination folder you can do a simple count for the number of files to be copied. You can use this code for that:

    # Count of number of files that will be copied
    "$((Get-ChildItem -Recurse -File -LiteralPath $SourceFolder).Count) files will be copied to $targetfolder"

    As for the status bar, progress report etc. This is something that cannot be done using the Copy-Item cmdlet when using recurse mode. You could use the Write-Progress cmdlet for this purpose but you would have to feed Get-ChildItem into Copy-Item instead of using the -Recurse parameter. You could get an approximate by displaying the files copied, bytes copied etc. If you have several big files and many small files it would make it slightly inaccurate.

    Here's a Write-Progress example:

    $Files = Get-ChildItem -LiteralPath $SourceFolder -Files
    $NumberofFiles = $Files.Count
    $Files | ForEach-Object -Begin {
        $FilesCopied = 0
    }
    -Progress {
        Write-Progress -Activity "Copying Files..." -PercentComplete [int](($FilesCopied/$NumberofFiles)*100) -CurrentOperation "$FilesCopied files copied out of total of $NumberofFiles files" -Status "Please wait."
        # Enter copy-item command here
        $FilesCopied++
    }


    It's a bit of a hassle but you can make it work this way. 


    Jaap Brasser
    http://www.jaapbrasser.com


    • Edited by Jaap BrasserMVP Wednesday, February 25, 2015 11:36 AM Missed a parameter
    Wednesday, February 25, 2015 11:36 AM
  • @Jaap

    Yes I want to overwrite existing files, since backup is taken care of by another script.

    Now I encounter this error when trying to use your write-progress example:

    Get-ChildItem : A parameter cannot be found that matches parameter name 'Files'.

    At line:3 char:51

    + $Files = Get-ChildItem -LiteralPath $SourceFolder -Files

    +                                                   ~~~~~~

        + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException

        + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

    cmdlet ForEach-Object at command pipeline position 1

    Supply values for the following parameters:

    Process[0]:

    Here is the script as I thought it should look like:

    $SourceFolder = "C:\Color1\TRID"
    $targetFolder = “C:\Color2”
    $Files = Get-ChildItem -LiteralPath $SourceFolder -Files
    $NumberofFiles = $Files.Count
    $Files | ForEach-Object -Begin {
        $FilesCopied = 0
        
        }
     -progress{
        Write-Progress -Activity "Copying Files..." -PercentComplete [int](($FilesCopied/$NumberofFiles)*100) -CurrentOperation "$FilesCopied files copied out of total of $NumberofFiles files" -Status "Please wait."
        
    "$((Get-ChildItem -Recurse -File -LiteralPath $SourceFolder).Count) files will be copied to $targetfolder"
    Read-Host -Prompt 'Press Enter to Start Copying...'
    Copy-Item $SourceFolder -Recurse -Destination $targetFolder -Force -verbose
     $FilesCopied++
    }
    # What is wrong now?

    Wednesday, February 25, 2015 1:28 PM
  • Why don't you want to use robocopy? It can log and show percentages. Why reinvent the wheel?

    -- Bill Stewart [Bill_Stewart]

    Wednesday, February 25, 2015 4:24 PM
  • Alright, that was because my code sample was using a parameter introduced in PowerShell v3, I have rewritten the code so it is compatible with PowerShell v2:

    $SourceFolder = "C:\Testing\Color1"
    $targetFolder = “C:\Testing\Color2”
    
    $Files = Get-ChildItem -LiteralPath $SourceFolder -Recurse | Where-Object {-not $_.PSIsContainer}
    $NumberofFiles = $Files.Count
    $TotalSizeGB = "{0:N2}" -f (($Files | Measure-Object -Property Length -Sum).Sum/1GB)
    $Files | ForEach-Object -Begin {
        $FilesCopied = 0
    } -Process {
        Write-Progress -Activity "Copying Files..." -PercentComplete ([int](($FilesCopied/$NumberofFiles)*100)) -CurrentOperation "$FilesCopied files copied out of total of $NumberofFiles files" -Status "Total Size: $TotalSizeGB GB, please wait while copying..."
        Copy-Item $_.FullName -Destination $targetFolder -Force
        $FilesCopied++
    }

    This is a basic example of how to use Write-Progress in combination with Copy-Item and it only works for a flat directory structure. If your source folder has any sub folders, the files will just be copied to the destination path which can cause the script to overwrite similarly named files. Furthermore there is no error handling of any kind and no logging. This can all be built in the script, but that would require significantly more coding. But it should give you an idea of how to do this in PowerShell.

    The reason I mention what this script cannot do is because robocopy can actually do this and works perfectly when launched from within PowerShell. So feel free to make your own decision on what you prefer to use, my personal recommendation would be to use robocopy. Happy scripting!


    Jaap Brasser
    http://www.jaapbrasser.com


    • Edited by Jaap BrasserMVP Thursday, February 26, 2015 1:30 AM Removed unnecessary parameter from code
    Thursday, February 26, 2015 1:28 AM
  • Agreed - you should not attempt to write a file-copying script unless 1) you have a really, really good reason for not using robocopy, and 2) you're an experienced script programmer.

    Robocopy has all kinds of features that are difficult to script. For example, it can retry on failed copies, it can throttle bandwidth usage when copying files over the network, it can mirror entire directory structures, etc.


    -- Bill Stewart [Bill_Stewart]

    Thursday, February 26, 2015 2:54 AM
  • Only to Things are problem here if you look only at Powershell. 1) I've tried robocopy in powershell with no luck of copying parentfolders with subfolders (including hidden files) while keeping folderstructur from A to B.

    2) PowerShell doesn't come with any built-in helpfiles for robocopy. Not even in Ps V4, as i'm using on my Windows 8.1 computer.

    3) I like the copy-item CMDlet much better. Beacuse it's an built-in feature in powershell.

    4) I do need that subfolders and hidden files are also copied and keep folder structur.

    Friday, February 27, 2015 8:34 AM
  • Robocopy can meet all of your requirements. Just type the robocopy command, followed by the parameters you want, and press Enter. It runs just fine in PowerShell. I have used it for years this way without problems.

    Robocopy documentation is readily available by a quick search.

    http://www.bing.com/search?q=robocopy documentation


    -- Bill Stewart [Bill_Stewart]

    • Proposed as answer by Bill_Stewart Tuesday, March 3, 2015 3:09 PM
    • Marked as answer by Bill_Stewart Friday, April 10, 2015 3:35 PM
    Friday, February 27, 2015 3:43 PM
  • 3) I like the copy-item CMDlet much better. Beacuse it's an built-in feature in powershell.

    4) I do need that subfolders and hidden files are also copied and keep folder structur.

    Well if you're set on using Copy-Item and you would really like to have Write-Progress then you'll have to code update the destination folder variable for each different folder you would like to copy to, then you'll have to verify that the folder exists and create the folder if it doesn't. Cmdlets you'll be needing are:

    • New-Item
    • Resolve-Path
    • Split-Path
    • Join-Path

    It is definitively possible to write this in PowerShell, like I said before it will be a bit of an effort in coding. And from what I understand from your description it is to do something which robocopy in particular was designed to do. So have a look at the robocopy documentation to find the parameters you need, I think in particular /E (or /S) might be of use to you.

    Anyway if you intend to script this and you are running into any roadblocks, feel free to post your code and I'll be happy to comment on it.


    Jaap Brasser
    http://www.jaapbrasser.com

    Saturday, February 28, 2015 3:26 AM