PowerShell : Get the most recently modified file for each directories

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 :

Get-ChildItem d:\tmp\* | Where {$_.PsIsContainer} | foreach-object { Get-ChildItem $_ -Recurse -ErrorAction SilentlyContinue | Where {!$_.PsIsContainer} | Select Name,DirectoryName, LastWriteTime, Mode | Sort LastWriteTime -descending | select -first 1}