PCs optimize

Use PowerShell to schedule routine tasks

Derek Schauland shares a simple PowerShell command that automates cleaning up old files on a set schedule.

Recently, when I logged on to my computer at the office, I noticed that there were piles of desktop shortcuts and other junk I dropped on the desktop that I probably didn't need to use again. I decided to use PowerShell to see if I could come up with an easy way to find all of the items that were put there over 180 days ago and then get rid of them.

This post outlines how I used PowerShell to look for old files and schedule an automated task that runs every day to delete them. This example of an everyday task illustrates how you can customize PowerShell commands to increase efficiency.

First things first - check for files

When I decided to try this bit of cleanup scripting, I first wanted to know if there were any files that were written longer than 180 days ago:

Get-childitem  -path "<path to desktop>" | where {$_.lastwritetime -lt (date).adddays(180)}
Note: <path to desktop> can be entered as c:\users\username\desktop on Windows Vista and later and C:\documents and settings\username\desktop on Windows XP, or you can navigate PowerShell to the path with cd users\username\desktop and leave the -path out of the command. Running this command on my system produced the results shown in Figure A below:

Figure A

Files on the desktop older than 180 days (click to enlarge)

Now that you know how many items there are on the desktop that you want to delete (or in any other folder you designate), you can schedule cleanup of these items. When I first ran this command, the number of files was a bit obscene, well over 500. Now that it is down to two files, that isn't too bad.

Scheduling a PowerShell command

To create a scheduled task that runs the above command, complete the following steps:

Schtasks /create /tn "Desktop Cleanup Task" /ru "domain\username" /rp <password for user entered> /sc daily /st 08:30 /tr "PowerShell -command {get-childitem c:\users\<username>\desktop | where{$_.lastwritetime -lt (date).adddays(-180)} | remove-item"

Whew, that seems like a ton of things to do in one line. Let's look at the pieces individually:

First we call schtasks and pass to it /create, which tells task scheduler that we want to create a task with the following attributes:

  • /tn - this is the name of the task, used to identify it when viewing scheduled tasks or modifying tasks previously created
  • /ru - this is the username (domain\username) used to run the task
  • /rp - the password for the account specified in /ru Note: I expected the command to prompt for a password if /rp was left out, but did not see that happen. That is the only reason it is specified here.
  • /sc daily - this is the schedule parameter -- I specified daily here
  • /st - the start time for the task -- in this example it is 8:30 am
  • /tr - this is the task to run -- here we call PowerShell and pass a command to the -command parameter

Now that the scheduled task portion is out of the way, all that is left is to build our PowerShell command, shown below:

"PowerShell -command {Get-childitem -path c:\users\username\desktop | where {$_.lastwritetime -lt (date).adddays(-180)} | remove-item}"
The entire command is enclosed in quotation marks to ensure it is handled together. The first section of the command is the same as the code used to check for files older than 180 days. Note: the curly braces following the -command parameter send all of the enclosed code as a script block. These are not required to run this command.

The only thing added to the original command is to pipe the output of the where{} section to remove-item, which will delete the items meeting the criteria of being older than 180 days.

When you enter the whole command in PowerShell, you will get a message (if everything is spelled correctly) that the task was created successfully. If the task name already exists you will be prompted to overwrite it with the new task.

What if I want to change the time?

Suppose you created this task and after a few months decide that you wanted to run it at 10:00 AM instead of 8:30 AM. You can simply use schtasks to change the time by entering the following at the PowerShell command line:

Schtasks /change /tn "Desktop Cleanup" /st 10:00

This will update the start time for the task to 10:00 AM. Your task with the new time will be visible in the Windows Task Scheduler.

Hopefully scheduling tasks from PowerShell to run PowerShell commands makes file cleanup other routine tasks a bit quicker for you. I know it has for me.

About

Derek Schauland has been tinkering with Windows systems since 1997. He has supported Windows NT 4, worked phone support for an ISP, and is currently the IT Manager for a manufacturing company in Wisconsin.

3 comments
CodeSculptor
CodeSculptor

Great (awesome) tip, and maybe it's just me... but here's my issue -- From Powershell I can test this Get-ChildItem -Filter audittrace201*.trc -path D:\,G:\ -recurse | where {$_.Lastwritetime -lt (get-date).addminutes(-720)} | remove-item -whatif And that works for me. But when I try this : powershell -command Get-ChildItem -Filter audittrace201*.trc -path D:\,G:\ -recurse | where {$_.Lastwritetime -lt (get-date).addminutes(-720)} | remove-item -whatif Then it says that the REMOVE-ITEM is not recognized as an internal command. That makes sense since it's powershell only. If I put it in quotes, then it works as : powershell -command "Get-ChildItem -Filter audittrace201*.trc -path D:\,G:\ -recurse | where {$_.Lastwritetime -lt (get-date).addminutes(-720)} | remove-item -whatif" And I have tried putting the entire block in curly-braces { } , with the same error. :( And there is the rub, because I can't embed quotes in the schtasks, can I? As : schtasks /create /ru "NT Authority\NETWORK SERVICE" /F /sc minute /mo 120 /tr "Powershell -command ""Get-ChildItem -Filter audittrace201*.trc -path D:\,G:\ -recurse | where {$_.Lastwritetime -lt (get-date).addminutes(-720)} | remove-item -whatif "" /TN "Prune Audit Files" Yes, I know, I don't put the whatif in there, but I wanted to make sure I won't clobber anyone's stuff if they cut and paste this. Are there solutions?

huskermiked
huskermiked

The date should be a negative number. That is looking for files that are older than 180 days in the future so naturally all files will be listed. Add a "-" before the number and it will magically work. I imagine that that was a typo in the original article that didn't get caught.

ian
ian

I tested the first part of the code and it returned five items, only two of which were from last year and older than 180 days.. The other three were from this month and only eight days old. I changed the date to 365, 90, 10 and 1 day. The result was the same. The 1 day should have picked up seven items from the desktop, so it seems something may be amiss with the code. Apart from that, I think it could be a nifty bit of code.