PowerShell : Get the most recently modified file for each directories
The most efficient way to work on Windows is using PowerShell.
You can do virtually anything with it. I’m just a newbie with PowerShell but here is how I work to construct complex commands with some basic knowledge.
Say I have some directories under D:\tmp and I want to know the more recently modified file for each directory.
First I have to list the content of my directory, so I use Get-ChildItem command (get-help Get-ChildItem for more information) :
PS C:\> Get-ChildItem D:\tmp\scripts -Recurse -ErrorAction SilentlyContinue Répertoire : D:\tmp\scripts Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 12/07/2012 17:28 LOGS -a--- 12/07/2012 17:28 1421 crdb1.sh -a--- 12/07/2012 17:28 526 crdb2.sh -a--- 12/07/2012 17:28 1245 crdb3.sh -a--- 12/07/2012 17:28 1368 crdb4.sh -a--- 12/07/2012 17:28 613 env.sh -a--- 12/07/2012 17:28 1034 initBDD.ora -a--- 12/07/2012 17:28 651 BDD.sh -a--- 12/07/2012 17:28 169 BDD.sql Répertoire : D:\tmp\scripts\LOGS Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 12/07/2012 17:28 1579 crdb1_BDD.log |
-Recurse will list recursively the directory, and -ErrorAction SilentlyContinue will ensure that the script will continue even if an error is raised.
Then I want only to work with files, so I use the property “PsIsContainer “ of the current object in the pipe (which is $_ similarly to Perl language).
I will add the “Where” statement to only select object that are not (so “!”) Containers (directories).
PS C:\> Get-ChildItem D:\tmp\scripts -Recurse -ErrorAction SilentlyContinue | Where {!$_.PsIsContainer} Répertoire : D:\tmp\scripts Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 12/07/2012 17:28 1421 crdb1.sh -a--- 12/07/2012 17:28 526 crdb2.sh -a--- 12/07/2012 17:28 1245 crdb3.sh -a--- 12/07/2012 17:28 1368 crdb4.sh -a--- 12/07/2012 17:28 613 env.sh -a--- 12/07/2012 17:28 1034 initBDD.ora -a--- 12/07/2012 17:28 651 BDD.sh -a--- 12/07/2012 17:28 169 BDD.sql Répertoire : D:\tmp\scripts\LOGS Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 12/07/2012 17:28 1579 crdb1_BDD.log |
From here I select the name of the columns I want to display to build a table:
PS C:\> Get-ChildItem D:\tmp\scripts -Recurse -ErrorAction SilentlyContinue | Where {!$_.PsIsContainer}|select Name,DirctoryName, LastWriteTime Name DirectoryName LastWriteTime ---- ------------- ------------- crdb1.sh D:\tmp\scripts 12/07/2012 17:28:13 crdb2.sh D:\tmp\scripts 12/07/2012 17:28:13 crdb3.sh D:\tmp\scripts 12/07/2012 17:28:13 crdb4.sh D:\tmp\scripts 12/07/2012 17:28:13 env.sh D:\tmp\scripts 12/07/2012 17:28:12 initBDD.ora D:\tmp\scripts 12/07/2012 17:28:13 BDD.sh D:\tmp\scripts 12/07/2012 17:28:12 BDD.sql D:\tmp\scripts 20/08/2012 15:52:25 crdb1_BDD.log D:\tmp\scripts\LOGS 12/07/2012 17:28:13 |
Sort them and only keep the most recent file :
PS C:\> Get-ChildItem D:\tmp\scripts -Recurse -ErrorAction SilentlyContinue | Where {!$_.PsIsContainer}|select Name,Dirc toryName, LastWriteTime |Sort LastWriteTime -descending | select -first 1 Name DirctoryName LastWriteTime ---- ------------ ------------- BDD.sql 20/08/2012 15:52:25 |
Now I have the name and most recently modified file of the directory.
If I want to do that on multiple directories, I will have to loop on every directory.
So I list all the objects of the upper directory and select only the Containers (or Directories).
PS C:\> Get-ChildItem d:\tmp\* | Where {$_.PsIsContainer} Répertoire : D:\tmp Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 16/07/2012 15:19 cpu-z_1.55-64bits-en d---- 19/07/2012 18:39 my07xx d---- 07/06/2012 14:47 graphs d---- 12/07/2012 17:28 scripts d---- 01/06/2012 17:24 SDD d---- 15/05/2012 12:05 sqr |
Then for each directory found you have to run the previous command. $_ will refer to the current directory on the foreach statement :
PS C:\> Get-ChildItem d:\tmp\* | Where {$_.PsIsContainer} | foreach-object { Get-ChildItem $_ -Recurse -ErrorAction Sile ntlyContinue | Where {!$_.PsIsContainer} | Select Name,DirectoryName, LastWriteTime, Mode | Sort LastWriteTime -descend ing | select -first 1} Name DirectoryName LastWriteTime Mode ---- ------------- ------------- ---- cpuz_readme.txt D:\tmp\cpu-z_1.55-64bits-en 09/07/2010 15:15:08 -a--- check_tinacat.ksh D:\tmp\my07xx 19/07/2012 18:39:18 -a--- tmpgraph.png D:\tmp\graphs\graphs\nmon_... 07/06/2012 14:39:04 -a--- BDD.sql D:\tmp\scripts 20/08/2012 15:52:25 -a--- deploysqrscript.txt D:\tmp\sqr 20/08/2012 16:09:47 -a--- |
On each line you will have the last modified file found for each directory under directly under “d:\tmp”
Command :