1: #----------------------------------------------------------------
2: # Find.ps1
3: #----------------------------------------------------------------
4: param
5: (
6: [string]$start = ".", # directory to start search in
7: [int]$maxdepth = -1, # decend at most "n" levels below starting line
8: [int]$mindepth = -1, # don't process levels less than mindepth
9: [int]$amin = -1, # file was last accessed "n" minutes ago
10: [int]$atime = -1, # file was last accessed "n"*24 hours ago
11: [bool]$empty = $false, # file is empty and is a file or directory.
12: [string]$name = "", # base of file name matches pattern.
13: [string]$path = "", # filename/path matches pattern.
14: [string]$exec = "" # Execute command on the matched files
15: );
16:
17: $script:CURRENT_DEPTH = 0;
18:
19: #----------------------------------------------------------------
20: # function Get-IsMatch
21: #----------------------------------------------------------------
22: function Get-IsMatch()
23: {
24: param
25: (
26: $info = $null,
27: $context = $null
28: );
29: [bool]$bIsMatch = $true;
30:
31: if ( Is-InDepthRange -context $context )
32: {
33: if ( $context["name"].Length -gt 0 )
34: {
35: $bIsMatch = $info.Name -like $context["name"];
36: }
37: elseif ( $context["path"].Length -gt 0 )
38: {
39: $bIsMatch = $info.FullName -like $context["path"];
40: }
41:
42: if ( $bIsMatch -and ($context["amin"] -ne -1) )
43: {
44: $ts = [DateTime]::Now - $info.LastAccessTime;
45: if ( $ts.TotalMinutes -gt $context["amin"] )
46: {
47: $bIsMatch = $false;
48: }
49: }
50:
51: if ( $bIsMatch -and ($context["atime"] -ne -1) )
52: {
53: $ts = [DateTime]::Now - $info.LastAccessTime;
54: if ( $ts.TotalHours -gt (24 * $context["atime"]) )
55: {
56: $bIsMatch = $false;
57: }
58: }
59:
60: $bIsEmpty = $false;
61: if ( $info -is [System.IO.FileInfo] )
62: {
63: $bIsEmpty = $info.Length -eq 0;
64: }
65: elseif ( $info -is [System.IO.DirectoryInfo] )
66: {
67: $bIsEmpty = ( $info.GetFiles().Length -eq 0 );
68: }
69: if ( $context["empty"] ) { $bIsMatch = $bIsEmpty; }
70: }
71: else
72: {
73: $bIsMatch = $false;
74: }
75:
76: $bIsMatch;
77: }
78:
79: #----------------------------------------------------------------
80: # function Is-InDepthRange
81: #----------------------------------------------------------------
82: function Is-InDepthRange()
83: {
84: param($context = $null);
85:
86: $bInRange = $true;
87: if ( $context )
88: {
89: if ( -1 -ne $context["mindepth"] )
90: {
91: if ( $script:CURRENT_DEPTH -lt $context["mindepth"] )
92: {
93: $bInRange = $false;
94: }
95: }
96: if ( -1 -ne $context["maxdepth"] )
97: {
98: if ( $script:CURRENT_DEPTH -gt $context["maxdepth"] )
99: {
100: $bInRange = $false;
101: }
102: }
103: }
104:
105: $bInRange;
106: }
107:
108: #----------------------------------------------------------------
109: # function Do-FindAction
110: #----------------------------------------------------------------
111: function Do-FindAction()
112: {
113: param
114: (
115: $info = $null,
116: $context = $null
117: );
118:
119: if ( $context["exec"].Length -gt 0 )
120: {
121: $cmd = $context["exec"];
122: $expr = $cmd.Replace("{}", "`$info");
123: Invoke-Expression $expr;
124: }
125: else
126: {
127: $info.FullName;
128: }
129: }
130:
131: #----------------------------------------------------------------
132: # function Find-InDirectory
133: #----------------------------------------------------------------
134: function Find-InDirectory()
135: {
136: param
137: (
138: [string]$location = ".", # directory to start search in
139: $context = $null
140: );
141:
142: $cis = @(Get-ChildItem -Path $location);
143: foreach ($ci in $cis)
144: {
145: if ( $ci.PSIsContainer )
146: {
147: if ( Get-IsMatch $ci -context $context )
148: {
149: Do-FindAction -info $ci -context $context;
150: }
151:
152: # Stop recursion if maxdepth is reached
153: if ( (-1 -ne $context["maxdepth"]) -and
154: (($script:CURRENT_DEPTH + 1) -gt $context["maxdepth"]) )
155: {
156: break;
157: }
158:
159: # Recurse through directories
160: $script:CURRENT_DEPTH++;
161: Find-InDirectory -location $ci.FullName -context $context;
162: $script:CURRENT_DEPTH--;
163: }
164: else
165: {
166: if ( Get-IsMatch $ci -context $context )
167: {
168: Do-FindAction -info $ci -context $context;
169: }
170: }
171: }
172: }
173:
174: #----------------------------------------------------------------
175: # function Do-Find
176: #----------------------------------------------------------------
177: function Do-Find()
178: {
179: param
180: (
181: [string]$start = ".",
182: [int]$maxdepth = -1,
183: [int]$mindepth = -1,
184: [int]$amin = -1,
185: [int]$atime = -1,
186: [bool]$empty = $false,
187: [string]$name = "",
188: [string]$path = "",
189: [string]$exec = ""
190: );
191:
192: $context = @{
193: "maxdepth" = $maxdepth; "mindepth" = $mindepth;
194: "amin" = $amin; "atime" = $atime;
195: "empty" = $empty; "name" = $name;
196: "path" = $path; "exec" = $exec};
197:
198: Find-InDirectory -location $start -context $context;
199: }
200:
201: Do-Find -start $start -maxdepth $maxdepth -mindepth $mindepth -amin $amin `
202: -atime $atime -empty $empty -name $name -path $path -exec $exec;