I recently read Todd Klindt's post on dynamically generating filenames based off of dates, for the greater purpose of making daily SharePoint backups.

USING BATCH FILES.

While his solution serves the #1 purpose of all scripts--it works, and thus is an excellent solution--I'd like to show how to accomplish the same thing using PowerShell.

Task #1: generate a SharePoint backup in YYMMDD format

DOS:

stsadm -o backup -url http://awesomeness.inc/ -filename "AwesomenessInc - %date:~-2%%date:~4,2%%date:~7,2%.backup.cab"

PowerShell:
(line breaks added for horizontal readability)

image

Task #2: delete backups older than seven days

DOS:

forfiles /d 7 /m *.backup.cab /c "cmd /c del @file"

PowerShell:
(line breaks added for horizontal readability)

image

Conclusions?

  • Both get the job done.
  • Date formatting in DOS is disgusting. forfiles is terse, but there's no excuse for the date formatting (substring selection?) syntax. This is almost as nasty as the fabled LDAP bitwise-and operator (look it up, it's not a joke).
  • PowerShell is far more verbose (at least today), but benefits us with improved readability.

Had I the inclination, I could have used standard procedural techniques to further express my intent in the code itself and further improve readability. E.g. instead of calculating the YYMMDD date inline in the string, I could have called a function to do that for me, or stored the value in a variable, i.e. either Get-TodayInYyMmDdFormat or $dateInYyMmDdFormat. So while I did an okay job readability-wise, I could have done better.

As for DOS: this is as good as it gets, readability-wise.

Aside: calling DOS commands from PowerShell

Final quick reminder: instead of all that PowerShell-specific nuttiness, we could have instead satisfied the "run this in PowerShell" requirement by prefixing the existing DOS commands with "cmd /c". So the DOS command

stsadm -o backup -url http://awesomeness.inc/ -filename "AwesomenessInc - %date:~-2%%date:~4,2%%date:~7,2%.backup.cab"

becomes the PowerShell-compatible command

cmd /c "stsadm -o backup -url http://awesomeness.inc/ -filename ""AwesomenessInc - %date:~-2%%date:~4,2%%date:~7,2%.backup.cab"""

Note that we're treating the entire line after cmd /c as a string in PowerShell, so we have to be sure to escape any special characters, e.g. the double-quote. While it's somewhat obvious when I encapsulate the entire DOSO command in the string, it is much less obvious if you fail to do so. PowerShell will attempt to 1) evaluate what is there, then, if it fails, 2) send that value to DOS as text. If you don't specifically tell the interpreter "hey, send this as text", you may be surprised by the results. An example of this oddness is something I've used before.

DOS:

stsadm | find "feature"

PowerShell:

stsadm | find """feature"""