Tuesday, September 17, 2013

Copy files modified in the last X days with Powershell

A friend asked on the weekend for some powershell that would allow him to copy files modified in the last 7 days to a new machine. It's a great opportunity to showcase the powershell pipeline feature!
get-childitem "c:\Source" | where-object {$_.LastWriteTime -gt (get-date).AddDays(-7)} | Copy-Item -destination "C:\Target"

This one liner will work for files in a folder (it'll get messy if we recurse though, there's a fix for that coming later).

See the pipe command '|' this used to pass the output of one command as input to another command.

  1. So we get-childitem (which is the powershell name for DIR) 
  2. then we pass that to where-object with a bit of code that looks at the creationtime property. the little $_. refers to the "next object in the pipeline" so we can hook into the properties of all the obejcts we found with get-childitem, perform an evaluation on the creation time,
  3. Then the object is passed to copy-item

Now if we want to be able to recursively do this we'll need to be a little more tricksy!

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
$source = "c:\users\benh\documents"
$target = "c:\test"

$files = get-childitem $source -Recurse
foreach ($file in $files)
{
    if ($file.LastWriteTime -ge (get-date).AddDays(-7))
    {
        $targetFile = $target + $file.FullName.SubString($source.Length)
        New-Item -ItemType File -Path $targetFile -Force
        Copy-Item $file.FullName -destination $targetFile
    }
}

This process uses a foreach loop which is similar to the pipeline in that it'll iterate through each item. But it allows us to use a complete script block which gives us a bit more power at the cost of performance. The main difference here is;
  1. We use an IF statement to evaluate how old the file is
  2. We figure out what the target path should be by dropping the $source directory from the files full name
  3. We create a new-item with the path we've established
  4. Then it's just copying the item as normal
Feel free to add and comments or if you've got a more elegant way of solving this problem let us know!





7 comments:

  1. Your script doesn't find files modified in the last 7 days, it finds files created in the last 7 days. Use $_.LastWriteTime to copy files modified in the last 7 days. There is a big difference.

    ReplyDelete
  2. Also use the -File option for get-childitem to only get files. e.g.

    $files = get-childitem -File $source -Recurse

    ReplyDelete
  3. Rather new to powershell and this script is working with the "Anonymous" chap's comments. However, I need the script to check whether a directory exists and if not then create a new one

    ReplyDelete
  4. This content material is written tremendously dexterously. Your use of formatting gone making your points makes your rationalization completely sure and easy to take. thank you. copy machine

    ReplyDelete
  5. Nice post! This is a very nice blog that I will definitively come back to more times this year! Thanks for informative post. office copier

    ReplyDelete