
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} |