none
Copy-item help for duplicate names with test-path RRS feed

  • Question

  • I am using this script to copy PST files to a shared location for import into Office 365.

    import-csv .\odep.csv | foreach {
    $UserName = $_.username
    $path = $_.path
    New-Item E:\PST\ODEP\$username -type directory
    $PST = Get-ChildItem $path -Filter *.pst -Recurse
    $PST | Copy-Item -Destination E:\PST\ODEP\$username -verbose
    }

    .I would like to modify it to use test-path to see if a file already exists and if it does to add a -1 to the end of it similar to this script but I can not get it to work properly when I combine the two

    $SourceFile = "\\ecnfile11\user\test\archives 2012.pst"
    $DestinationFile = "C:\temp\pst-test\archives 2012.pst"

    If (Test-Path $DestinationFile) {
        $i = 0
        While (Test-Path $DestinationFile) {
            $i += -1
            $DestinationFile = "C:\temp\pst-test\archives 2012$i.pst"
        }
    } Else {
        New-Item -ItemType File -Path $DestinationFile -Force
    }

    Copy-Item -Path $SourceFile -Destination $DestinationFile -Force

    I think it i scholing on the $PST variable but not sure.

    Anyone have any ideas?

    Thanks for your time!


    • Edited by chabango Thursday, August 11, 2016 5:13 PM
    Thursday, August 11, 2016 4:06 PM

Answers

  • Ahhh...Figured this out...

    Moving the $i = 1 line to inside the ForEach loop of the get-childitem

    $csv = import-csv .\test.csv
    foreach ($line in $csv) {
        New-Item c:\new-pst\$($line.username) -type directory
    
        $dest = "c:\new-pst\$($line.username)"
     ##  $i=1 Note the ORIGINAL position of the initializer
    
        Get-ChildItem -Path $line.path -Filter *.pst -Recurse | ForEach-Object {
    
            $i=1 # Note the NEW position of the initializer
            $nextName = Join-Path -Path $dest -ChildPath $_.name
    
            while(Test-Path -Path $nextName)
            {
               $nextName = Join-Path $dest ($_.BaseName + "_$i" + $_.Extension)
               $i++  
            }
    
            $_ | copy-Item -Destination $nextName -verbose
        }
    }


    • Marked as answer by chabango Thursday, September 8, 2016 6:33 PM
    Thursday, September 8, 2016 6:32 PM

All replies

  • Like this:

    $SourceFile = "\\ecnfile11\bost-charles-j$\test\archives 2012.pst"
    
    $DestinationFile = "C:\temp\pst-test\archives 2012.pst"
    $i=1
    While (Test-Path $DestinationFile) {
    	$DestinationFile = "C:\temp\pst-test\archives 2012-$i.pst"
    	$i++
    }
    Copy-Item -Path $SourceFile -Destination $DestinationFile



    \_(ツ)_/

    Thursday, August 11, 2016 4:22 PM
    Moderator
  • That works if i define the source and destination files, but I need to be able to use the import-csv for numerous files.

    How can I add that to this?


    $SourceFile = "import-csv .\sourcefiles.csv
    $DestinationFile = "e:\PST\$username"

    If (Test-Path $DestinationFile) {
        $i = 0
        While (Test-Path $DestinationFile) {
            $i += -1
            $DestinationFile = "e:\PST\$username\????????$i.pst"
        }
    } Else {
        New-Item -ItemType File -Path $DestinationFile -Force
    }

    Copy-Item -Path $SourceFile -Destination $DestinationFile -Force

    Thursday, August 11, 2016 4:29 PM
  • Why did you change the code? I posted all of the code you need.

    You do not need an "if" or New-Item. They actually do nothing.

    Just loop on output from CSV and use the CSV variables.


    \_(ツ)_/


    Thursday, August 11, 2016 4:31 PM
    Moderator
  • ok.

    Excuse my lack of knowledge, how do I loop on output from CSV and use the CSV variables  in this script?

    $SourceFile = "\\ecnfile11\user$\test\archives 2012.pst"

    $DestinationFile = "C:\temp\pst-test\archives 2012.pst"
    $i=1
    While (Test-Path $DestinationFile) {
        $DestinationFile = "C:\temp\pst-test\archives 2012-$i.pst"
        $i++
    }
    Copy-Item -Path $SourceFile -Destination $DestinationFile


    • Edited by chabango Thursday, August 11, 2016 5:14 PM
    Thursday, August 11, 2016 4:35 PM
  • help foreach
    help Import-CSV -full

    Always read all of the help for any syntax element or CmdLet.  90% of all answers are in the help.  Using help is the first and most important thing any programmer must do in any system.

    help help

    Wiill get you started.


    \_(ツ)_/

    Thursday, August 11, 2016 4:47 PM
    Moderator
  • I am getting closer but when it loops through again, it fails because the file already exists:

    import-csv .\test1.csv | foreach {
    $path = $_.path
    $username = $_.username
    $dest = "C:\temp\pst-test\$username"
    $i = 1
    New-Item c:\temp\pst-test\$username -type directory
    $pst=Get-ChildItem $path -filter *.PST –recurse
    $pst
    foreach ($file in $pst) {
    $dir

    While (Test-Path $DestinationFile) {
        $DestinationFile = "C:\temp\pst-test\$username\$($pst.Name-$i)"
        $i++
    }
    Copy-Item -Path $file.fullname -Destination C:\temp\pst-test\$username

    }}

    Tuesday, August 16, 2016 2:44 PM
  • Why do you insist on changing the code I posted.  It works perfectly.  You keep wrapping your bad code around the solution and it fails.

    You have to simplify.  Throw away every piece of code you do not understand and start from scratch.  Use messages to track what is happening until you understand.  Ad a new piece of code and watch what happens.


    \_(ツ)_/

    Tuesday, August 16, 2016 5:15 PM
    Moderator
  • I am playing with the code because I am trying to learn. I am having a hard time with the destination file in the while statement.

    I was able to get this work but when it increments the files it does not start at 1 when a new file name is used. For example, if i have a 3 files in different directories named test.pst, it will copy them as test.pst, test-1.pst and test-3.pst. However, the next file that it copies will not start at 1 again for the duplicate. for example, test2.pst  will copy as test3.pst then the duplicate will be test2-4.pst instead of test2-1.pst. it continues the numbering where the test left off. how can i modify this to work like you have it with the variables:

    $csv = import-csv .\test.csv
    foreach ($line in $csv) {
    New-Item c:\new-pst\$($line.username) -type directory

    $dest = "c:\new-pst\$($line.username)"
    $i=1

    Get-ChildItem -Path $line.path -Filter *.pst -Recurse | ForEach-Object {
        
        
        $nextName = "$dest\$_.name"

        while(Test-Path -Path $nextName)
        {
      #line where i am having the issue:  

      $nextName = $nextName = Join-Path $dest ($_.BaseName + "_$i" + $_.Extension)  
           $i++  
        }

        $_ | copy-Item -Destination $nextName -verbose
    }
    }

    Wednesday, September 7, 2016 6:52 PM
  • It is very hard to understand what you are trying to accomplish by numbering the files.  If you can create a clear statement of intent then it will be easier for you to create the code.  You also need to use the code posting tool so that your code is readable:

    Like this:

    $csv = import-csv .\test.csv
    foreach ($line in $csv) {
    	New-Item c:\new-pst\$($line.username) -type directory
    	$dest = "c:\new-pst\$($line.username)"
    	$i = 1
    	Get-ChildItem -Path $line.path -Filter *.pst -Recurse | 
    		ForEach-Object{
    			$nextName = "$dest\$_.name"
    			while (Test-Path -Path $nextName) {
    				#line where i am having the issue:   
    				$nextName = $nextName = Join-Path $dest ($_.BaseName + "_$i" + $_.Extension)
    				$i++
    			}
    			$_ | copy-Item -Destination $nextName -verbose
    		}
    }
    

    You can use ISE to help you format your code so that it is readable.  The posting tool will maintain the format an colored syntax.


    \_(ツ)_/

    Wednesday, September 7, 2016 6:58 PM
    Moderator
  • My best guess is that this is what you are trying to do:

    $csv = import-csv .\test.csv
    foreach ($line in $csv) {
    	$dest = Join-Path c:\new-pst $line.username
    	New-Item $dest -type directory -Force
    	$i = 1
    	Get-ChildItem -Path $line.path -Filter *.pst -Recurse | 
    		ForEach-Object{
    			$nextName = Join-Path $dest $_.name
    			while (Test-Path -Path $nextName) {
    				$nextName = Join-Path $dest ($_.BaseName + $i + $_.Extension)
    				$i++
    			}
    			$_ | copy-Item -Destination $nextName -verbose
    		}
    }


    \_(ツ)_/


    • Edited by jrvModerator Wednesday, September 7, 2016 7:04 PM
    Wednesday, September 7, 2016 7:03 PM
    Moderator
  • I have a list of users that I am searching their shared drives for PST files. I am using a csv file with the headers username and path.

    I am using the username to create a new directory in the destination (new-item ....)

    When I crawl the user's shared drive using the get-childitem i am copying them to a destination based on the new-item created above. the script i have below works except for what I outlined above:

    "I was able to get this work but when it increments the files it does not start at 1 when a new file name is used. For example, if i have a 3 files in different directories named test.pst for the user Joe.Smith, it will copy them as test.pst, test-1.pst and test-3.pst. However, the next file that it copies for Joe.Smith that is a duplicate will not start at 1 again for the duplicate. for example, test2.pst  will copy as test3.pst then the duplicate will be test2-4.pst instead of test2-1.pst. it continues the numbering where the test left off. how can i modify this to work like you have it with the variables:"

    output for example: you'll notice that test3.pst copise fine, but when if finds another file names test3.pst, it copies it as test3-3.pst instead of renaming it tes3-1.pst. Same for test2.

    VERBOSE: Performing the operation "Copy File" on target "Item: C:\pst\bost\folder2\Test.pst Destination: C:\new-pst\bost\Test.pst.name".
    VERBOSE: Performing the operation "Copy File" on target "Item: C:\pst\bost\folder2\Test2.pst Destination: C:\new-pst\bost\Test2.pst.name".
    VERBOSE: Performing the operation "Copy File" on target "Item: C:\pst\bost\folder2\Test3.pst Destination: C:\new-pst\bost\Test3.pst.name".
    VERBOSE: Performing the operation "Copy File" on target "Item: C:\pst\bost\myfoler\Test.pst Destination: C:\new-pst\bost\Test_1.pst".
    VERBOSE: Performing the operation "Copy File" on target "Item: C:\pst\bost\myfoler\Test2.pst Destination: C:\new-pst\bost\Test2_2.pst".
    VERBOSE: Performing the operation "Copy File" on target "Item: C:\pst\bost\myfoler\Test3.pst Destination: C:\new-pst\bost\Test3_3.pst"

    $csv = import-csv .\test.csv
    foreach ($line in $csv) {
    New-Item c:\new-pst\$($line.username) -type directory
    
    $dest = "c:\new-pst\$($line.username)"
    $i=1
    
    Get-ChildItem -Path $line.path -Filter *.pst -Recurse | ForEach-Object {
        
        
        $nextName = Join-Path -Path $dest -ChildPath $_.name
    
        while(Test-Path -Path $nextName)
        {
           $nextName = Join-Path $dest ($_.BaseName + "_$i" + $_.Extension)    
           $i++  
        }
    
        $_ | copy-Item -Destination $nextName -verbose
    }
    }

    Wednesday, September 7, 2016 7:40 PM
  • The code I posted cannot do that.  You are missing some key piece of information.

    \_(ツ)_/

    Wednesday, September 7, 2016 7:51 PM
    Moderator
  • Hi jrv,

    The code i have posted below does that and it works. My question and the problem I am having with it is that when it renames the pst it continues to increment the number. For example, if it finds a file named test.pst it will copy it as is. if it finds another .pst also named test.pst, it will copy it and rename it test-1.pst which is fine. However, if it finds 2 files named test2.pst it will copy the first one as test2.pst and copy and rename the second one to test2-2.pst instead of test2-1.pst. Do you have any suggestions on how I can modify my code so that it will start numbering each new duplicate file with 1 (test3-1.pst, test4-1.pst, etc)?

    this line of code i am referring to is this portion:

           $nextName = Join-Path $dest ($_.BaseName + "_$i" + $_.Extension)    
           $i++ 

    $csv = import-csv .\test.csv
    foreach ($line in $csv) {
    New-Item c:\new-pst\$($line.username) -type directory
    
    $dest = "c:\new-pst\$($line.username)"
    $i=1
    
    Get-ChildItem -Path $line.path -Filter *.pst -Recurse | ForEach-Object {
        
        
        $nextName = Join-Path -Path $dest -ChildPath $_.name
    
        while(Test-Path -Path $nextName)
        {
           $nextName = Join-Path $dest ($_.BaseName + "_$i" + $_.Extension)    
           $i++  
        }
    
        $_ | copy-Item -Destination $nextName -verbose
    }
    }

    Thursday, September 8, 2016 12:50 PM
  • Place Write-Host statements in the code to see what is happening.  Trace original file names and generated names.  The code, as I see it, cannot do what you are claiming so I suspect there s something else going on. Since I don't have you system I cannot test your data.

    \_(ツ)_/

    Thursday, September 8, 2016 12:54 PM
    Moderator
  • I will try to test what you have suggested. I have tried the code as written  on two different laptops and it works (aside from the numbering issue). It creates the new directory for each username and then loops through each path and copies the PSTs to the new directory.
    Thursday, September 8, 2016 1:12 PM
  • Ahhh...Figured this out...

    Moving the $i = 1 line to inside the ForEach loop of the get-childitem

    $csv = import-csv .\test.csv
    foreach ($line in $csv) {
        New-Item c:\new-pst\$($line.username) -type directory
    
        $dest = "c:\new-pst\$($line.username)"
     ##  $i=1 Note the ORIGINAL position of the initializer
    
        Get-ChildItem -Path $line.path -Filter *.pst -Recurse | ForEach-Object {
    
            $i=1 # Note the NEW position of the initializer
            $nextName = Join-Path -Path $dest -ChildPath $_.name
    
            while(Test-Path -Path $nextName)
            {
               $nextName = Join-Path $dest ($_.BaseName + "_$i" + $_.Extension)
               $i++  
            }
    
            $_ | copy-Item -Destination $nextName -verbose
        }
    }


    • Marked as answer by chabango Thursday, September 8, 2016 6:33 PM
    Thursday, September 8, 2016 6:32 PM