{"id":54723,"date":"2008-12-30T11:43:00","date_gmt":"2008-12-30T11:43:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/12\/30\/hey-scripting-guy-how-do-i-back-up-files-that-have-been-modified-in-the-last-day\/"},"modified":"2008-12-30T11:43:00","modified_gmt":"2008-12-30T11:43:00","slug":"hey-scripting-guy-how-do-i-back-up-files-that-have-been-modified-in-the-last-day","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-do-i-back-up-files-that-have-been-modified-in-the-last-day\/","title":{"rendered":"Hey, Scripting Guy! How Do I Back Up Files That Have Been Modified in the Last Day?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/H2>\n<P>Hey, Scripting Guy! I have a USB drive that I use for backup purposes on my computer. Because it appears that Windows Vista does not have a backup program that I can use, I thought it would be useful to write a script using Windows PowerShell to back up the computer. To make things simple, I have all my data in a folder called &#8220;data.&#8221; I only want to copy files that have changed within the last day to a folder on the USB drive that is automatically created based upon the date and time. Can this be done easily?<BR><BR>&#8211; MS<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hi MS,<\/P>\n<P>First of all, Windows Vista does have a back up and restore program. It is actually pretty cool, and does a very good job. Here is <A href=\"http:\/\/www.microsoft.com\/windows\/windows-vista\/features\/backup.aspx\" target=\"_blank\">an article<\/A> that talks about this feature. What the redesigned program does not do is selective backup and restore. As a computer professional, I also find this missing feature somewhat annoying. However, when thinking about desktops, laptops, and all that, most of the users have never used a backup program in their lives, and they are not fully in tune with the backup process. So the ability to do a system backup and restore, while useful, unfortunately does not meet our needs here. Luckily, we can easily solve this problem with Windows PowerShell.<\/P>\n<P>For information about working with files and folders in Windows PowerShell see <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/pstips\/oct07\/pstip1005.mspx\" target=\"_blank\">this article<\/A>. You may also wish to see <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/msh\/cmdlets\/files.mspx\" target=\"_blank\">this section<\/A> of &#8220;What Can I Do with Windows PowerShell&#8221; that deals specifically with files and folders. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\" target=\"_blank\">Windows PowerShell scripting hub<\/A> is a good place to get started with Windows PowerShell, and it includes download links and other items of use. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/begin\/archive.mspx\" target=\"_blank\">Sesame Script archive<\/A> has several VBScript articles dealing with files and folders. They are worth a look for VBScript examples. The community script repository has a good selection of <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/csc\/scripts\/files\/default.mspx\" target=\"_blank\">files and folders scripts<\/A> in VBscript. You also may want to check the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/files.mspx\" target=\"_blank\">Hey, Scripting Guy! archive<\/A> for a number of VBScript examples of working with files and folders. <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/dec07\/hey1211.mspx\" target=\"_blank\">This script<\/A> deletes files older than a certain number of hours, which kind of illustrates part of what we are doing here.<\/P>\n<P>In today\u2019s script, we create two functions. The first function creates the backup folder based upon the date and time the script is run. The second function backs up the files that have been modified in the last day. You can of course change the destination, the source, and the interval. The script is seen&nbsp;here:<\/P><PRE class=\"codeSample\">Function New-BackUpFolder($destinationFolder)\n{\n $dte = get-date\n $dte = $dte.tostring() -replace &#8220;[:\\s\/]&#8221;, &#8220;.&#8221;\n $backUpPath = &#8220;$destinationFolder&#8221; + $dte\n $null = New-Item -path $backUpPath -itemType directory\n New-Backup $dataFolder $backUpPath $backUpInterval\n} #end New-BackUpFolder<\/p>\n<p>Function New-Backup($dataFolder,$backUpPath,$backUpInterval)\n{\n &#8220;backing up $dataFolder&#8230; check $backUppath for your files&#8221;\n Get-Childitem -path $dataFolder -recurse |\n Where-Object { $_.LastWriteTime -ge (get-date).addDays(-$backUpInterval) } |\n Foreach-Object { copy-item -path $_.FullName -destination $backUpPath -force }\n} #end New-BackUp<\/p>\n<p># *** entry point to script ***<\/p>\n<p>$backUpInterval = 1\n$dataFolder = &#8220;C:\\fso&#8221;\n$destinationFolder = &#8220;C:\\BU\\&#8221;\nNew-BackupFolder $destinationFolder\n<\/PRE>\n<P>The essential functionality of this script is contained in two functions. The advantage of this approach to scripting is that it makes the script easier to read, easier to test, easier to modify, and easier to reuse if you should desire to do so later. A good function should encapsulate a single thought, idea, or piece of functionality. In addition, it is a best practice to follow the verb\/noun <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/winpsh\/cmdline_std.mspx\" target=\"_blank\">naming convention<\/A> set up by the Windows PowerShell team. This will become much more important in Windows PowerShell 2.0. <\/P>\n<P>The objective of our script is to back up files that have been modified in the last day. Here is the target folder we will use:<\/P><IMG height=\"341\" alt=\"Image of the target folder\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1230\/hsg_ff2_01.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>The first function begins with the <B>function<\/B> keyword, and names the new function <B>New-BackUpFolder<\/B>. It takes a single input, which is the path to the destination folder. This is seen here: <\/P><PRE class=\"codeSample\">Function New-BackUpFolder($destinationFolder)<\/PRE>\n<P>Next we use the <B>get-date<\/B> cmdlet to retrieve the current date and time. We store this in a variable named <B>$dte<\/B> as seen here: <\/P><PRE class=\"codeSample\">$dte = get-date<\/PRE>\n<P>Now we want to turn the <B>datetime<\/B> object that was returned by the <B>get-date<\/B> cmdlet into a string. To do this, we use the <B>tostring()<\/B> method. When we have a string, we have something that looks like&nbsp;this:<\/P><PRE class=\"codeSample\">PS C:\\&gt; (get-date).tostring()\n12\/12\/2008 1:00:59 PM\n<\/PRE>\n<P>The problem is that we are not allowed to have some of those characters in a file name. The answer is to use a regular expression pattern to fix the string so that we can use it for a folder name. The <B>replace<\/B> operator allows us to use regular expressions. Regular expressions are talked about in the Microsoft Press book, <A href=\"http:\/\/www.microsoft.com\/MSPress\/books\/authors\/auth9541.aspx\" target=\"_blank\">Windows PowerShell Scripting Guide<\/A>; they are also documented on <A href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/hs600312.aspx\" target=\"_blank\">MSDN<\/A>. <\/P>\n<P>The first thing the pattern does is replace the colon with a period, which is the same&nbsp;as:<\/P><PRE class=\"codeSample\">PS C:\\&gt; (get-date).tostring() -replace &#8220;:&#8221;, &#8220;.&#8221;\n12\/12\/2008 1.09.53 PM\n<\/PRE>\n<P>The next thing the pattern does is use <B>\\s<\/B> to replace all the spaces with a period. This is seen&nbsp;here:<\/P><PRE class=\"codeSample\">PS C:\\&gt; (get-date).tostring() -replace &#8220;\\s&#8221;, &#8220;.&#8221;\n12\/12\/2008.1:11:07.PM\n<\/PRE>\n<P>The last thing the pattern does is replace the forward slash with a period. This is seen&nbsp;here:<\/P><PRE class=\"codeSample\">PS C:\\&gt; (get-date).tostring() -replace &#8220;\/&#8221;, &#8220;.&#8221;\n12.12.2008 1:11:56 PM\n<\/PRE>\n<P>When you put them all together, you get the pattern seen here. The square brackets are used when you want to supply a more complex match pattern: <\/P><PRE class=\"codeSample\">$dte = $dte.tostring() -replace &#8220;[:\\s\/]&#8221;, &#8220;.&#8221;<\/PRE>\n<P>The complete path to the backup location is a combination of <B>$destinationfolder<\/B> and the date time stamp that we created in the previous step. This is stored in the variable <B>$backUpPath<\/B> as seen here: <\/P><PRE class=\"codeSample\">$backUpPath = &#8220;$destinationFolder&#8221; + $dte<\/PRE>\n<P>Now we want to create the backup folder. To do this, we use the <B>New-Item<\/B> cmdlet. We give this cmdlet the path we stored in the <B>$backUpPath<\/B> variable, and tell it we are creating an <B>itemtype<\/B> that is a directory. This is seen here:<\/P><PRE class=\"codeSample\">$null = New-Item -path $backUpPath -itemType directory<\/PRE>\n<P>The result of this section of the script is a folder which is seen in the image that follows this paragraph. As seen in the image, each time the script is run, a new subfolder is created. You can run the script once a second and never receive an error. However, if you run it more than once a second, you will get a duplicate folder error message: <\/P><IMG height=\"341\" alt=\"Image of each new subfolder created every time the script is run\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1230\/hsg_ff2_02.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>Now we need to call the <B>New-Backup<\/B> function. The <B>New-Backup<\/B> function takes three parameters: <B>$dataFolder<\/B>, <B>$BackUpPath<\/B>, and <B>$backUpInterval<\/B>. This is seen here: <\/P><PRE class=\"codeSample\">New-Backup $dataFolder $backUpPath $backUpInterval<\/PRE>\n<P>In the code we use to create the <B>New-Backup<\/B> function, we define the input parameters. If one of these values is missing when the function is called, the script will generate an error: <\/P><PRE class=\"codeSample\">Function New-Backup($dataFolder,$backUpPath,$backUpInterval)<\/PRE>\n<P>We print out a message that lets the user know that the script is backing up the folder, and we also print the destination that is being used. This is seen here: <\/P><PRE class=\"codeSample\">&#8220;backing up $dataFolder&#8230; check $backUppath for your files&#8221;<\/PRE>\n<P><B>Get-ChildItem<\/B> is used to retrieve a listing of all the files in the folder. The collection of files is sent across the pipeline to the <B>Where-Object<\/B> that will filter out the files: <\/P><PRE class=\"codeSample\">Get-Childitem -path $dataFolder -recurse |<\/PRE>\n<P>We use the <B>Where-Object<\/B> to filter out the <B>LastWriteTime<\/B> attribute of the files. If the last write time was greater than the number of days represented by <B>$backUpInterval<\/B> when subtracted from the current date, we will copy the file. To figure the date, we use the <B>addDays<\/B> method from the <B>datetime<\/B> object that is returned by the <B>Get-Date<\/B> cmdlet. The cool thing is that <B>addDays<\/B> will accept a negative number, which means you do not need a <B>subtractDays<\/B> method. This is seen here: <\/P><PRE class=\"codeSample\">Where-Object { $_.LastWriteTime -ge (get-date).addDays(-$backUpInterval) } |<\/PRE>\n<P>To work with each individual file, we need to use the <B>Foreach-Object<\/B> cmdlet. Each file that makes it through the <B>Where-Object<\/B> filter is then copied by using the <B>Copy-Item<\/B> cmdlet. It copies files from the path that is obtained via the <B>fullname<\/B> property of the current item on the pipeline. The destination is stored in the <B>$backUpPath<\/B> folder. The <B>\u2013force<\/B> parameter is not really needed, but is there to force overwriting a file if it happened to exist: <\/P><PRE class=\"codeSample\">Foreach-Object { copy-item -path $_.FullName -destination $backUpPath -force }<\/PRE>\n<P>The entry point to the script defines three variables and calls the <B>New-backUpFolder<\/B> function, as seen here: <\/P><PRE class=\"codeSample\">$backUpInterval = 1\n$dataFolder = &#8220;C:\\fso&#8221;\n$destinationFolder = &#8220;C:\\BU\\&#8221;\nNew-BackupFolder $destinationFolder\n<\/PRE>\n<P>When we look at the results of the script, we see that only a couple of the files were actually copied. These are the recently changed ones, which was our objective: <\/P><IMG height=\"341\" alt=\"The screen changes when the user types 'y'\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1230\/hsg_ff2_03.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>MS, it looks as if we wound up with a pretty cool script. It is something that should prove useful to you. See you tomorrow\u2014the last day of 2008.<\/P>\n<P><FONT class=\"Apple-style-span\" face=\"Verdana\" size=\"3\"><SPAN class=\"Apple-style-span\"><B><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/B><\/SPAN><\/FONT><\/P><FONT class=\"Apple-style-span\" face=\"Verdana\" size=\"3\"><B><\/B><\/FONT><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have a USB drive that I use for backup purposes on my computer. Because it appears that Windows Vista does not have a backup program that I can use, I thought it would be useful to write a script using Windows PowerShell to back up the computer. To make things simple, [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[38,3,12,45],"class_list":["post-54723","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-files","tag-scripting-guy","tag-storage","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have a USB drive that I use for backup purposes on my computer. Because it appears that Windows Vista does not have a backup program that I can use, I thought it would be useful to write a script using Windows PowerShell to back up the computer. To make things simple, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54723"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54723\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}