4

Total N00b to Powershell and have already got a script that uses Robocopy to copy files and their directory structure to another folder, and a second that then copies them from the subfolders to the root folder. Yes, I've tried searching but can't find anything that helps.

This is the Powershell command for the second step:

get-childitem -rec -include *.* | copy-item -destination 'yourpath'

Is there anything I can add to this so that it doesn't copy files that already exist (according to filename) in the destination directory, ie the root of the folder structure?

Thanks in advance

mandrill
  • 91
  • 1
  • 8
  • 2
    Enclose your copy-item command in a IF block that tests for the existence of the file at the destination. – Tony Hinkle May 04 '15 at 15:26
  • Thanks @TonyHinkle So I basically need it to check each item that it finds in the subfolders doesn't already exist in the main folder. Tried this: `get-childitem -rec -include *.* | if(!(Test-Path -Path 'C:\Users\Public\Tictocwatches v2.0\Images\Images Matched to Current Data 03-05-2015')) { copy-item -destination 'C:\Users\Public\Tictocwatches v2.0\Images\Images Matched to Current Data 03-05-2015' }` But it says that the if is not valid or is in the wrong place. (there are probably a whole slew of other errors in there too, but that's the one that powershell throws up at me.) – mandrill May 04 '15 at 15:54
  • Thank you @GrahamGold, as I said I had searched but didn't come up with anything. That seems to do what I want or at least points me in the right direction. :) – mandrill May 05 '15 at 09:07
  • Once again @GrahamGold thank you that seems to have done the job. Is there any way to redirect people to that thread more prominently? – mandrill May 05 '15 at 10:45
  • This has been answered by: http://stackoverflow.com/a/17497953/1386721 Thanks all for your input :) – mandrill May 05 '15 at 10:50
  • @mandrill - note that the accepted answer in that post may perform more poorly and/or consume more resources with a large number of files as it stores a collection and then iterates over it again. – dugas May 05 '15 at 14:39
  • @mandrill yep the mods have accepted my flagging of your post as a duplicate of that one, so this now has a more prominent link to that. Other than that it comes down to what you put in your search text :-) – Graham Gold May 05 '15 at 17:44
  • @dugas as the author of the accepted answer in the other question, more than happy to be told how to do it more efficiently whilst retaining the functionally the OP in that question asked for :-) – Graham Gold May 05 '15 at 17:46
  • 1
    @GrahamGold - you could move your test for the existence of the file into the condition of the Where-Object before the cop-item cmdlet, like in my answer on this post. – dugas May 05 '15 at 18:05

1 Answers1

4

One option would be to pipe the output of get-childitem to the Test-Path cmdlet to check for the existence of the file at the destination:

get-childitem -rec -include *.* | ? { !(Test-Path "yourpath\$($_.Name)") } | copy-item -destination 'yourpath'
dugas
  • 12,025
  • 3
  • 45
  • 51
  • 1
    The method I hacked out is `get-childitem -rec -include *.* | Foreach-object {If (-Not (Test-path $target$_.)) {copy-item -path $_.fullname -destination $target$_}}` I'm obviously not the Powershell guru that @dugas is. :) – Tony Hinkle May 04 '15 at 15:59
  • @dugas is no guru :) – dugas May 04 '15 at 16:11
  • couple of questions: 1 - Can I restrict get-childitem to _only_ looking in the subfolders for files with a specific extension? Will save a lot of processing if it simply ignores the files already existing in the root folder. (I'm guessing that it would be something like ./*/*.jpg instead of *.*, I'm probably wrong though.) 2 - dugas I take it I can just insert my absolute path in where it says 'yourpath' and can keep everything inside the quotes even though the path has spaces in it? 3 - @TonyHinkle: doesn't $target$_. need to be set as a variable somewhere? – mandrill May 05 '15 at 10:28
  • To just get the subdirectories, start with another get-childitem that returns only folders (filters on PSIsContainer): `Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | get-childitem -rec -include *.* | ? { !(Test-Path "yourpath\$($_.Name)") } | copy-item -destination 'yourpath'` – Tony Hinkle May 05 '15 at 12:51
  • And yes, $target would a variable that I used instead of putting the path name there as a string. It could also be written as `'d:\mypath'$_` – Tony Hinkle May 05 '15 at 12:54