1 |
#Region "Microsoft.VisualBasic::c6795b3109517c1ff0cd60caae3da7fd, Microsoft.VisualBasic.Core\Extensions\IO\Extensions\PathExtensions.vb"
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
#End Region
|
50 |
|
51 |
Imports System.Collections.ObjectModel
|
52 |
Imports System.IO
|
53 |
Imports System.Math
|
54 |
Imports System.Reflection
|
55 |
Imports System.Runtime.CompilerServices
|
56 |
Imports System.Text
|
57 |
Imports System.Text.RegularExpressions
|
58 |
Imports Microsoft.VisualBasic.CommandLine.Reflection
|
59 |
Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
|
60 |
Imports Microsoft.VisualBasic.FileIO
|
61 |
Imports Microsoft.VisualBasic.FileIO.Path
|
62 |
Imports Microsoft.VisualBasic.Language
|
63 |
Imports Microsoft.VisualBasic.Language.Default
|
64 |
Imports Microsoft.VisualBasic.Language.UnixBash
|
65 |
Imports Microsoft.VisualBasic.Linq.Extensions
|
66 |
Imports Microsoft.VisualBasic.Scripting.MetaData
|
67 |
Imports Microsoft.VisualBasic.Serialization.JSON
|
68 |
Imports Microsoft.VisualBasic.Text
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
<Package("Program.Path.Search", Description:="A utility tools for searching a specific file of its path on the file system more easily.")>
|
75 |
Public Module PathExtensions
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
85 |
<Extension>
|
86 |
Public Function ChangeSuffix(path$, newSuffix$) As String
|
87 |
Return path.TrimSuffix & "." & newSuffix
|
88 |
End Function
|
89 |
|
90 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
91 |
<Extension>
|
92 |
Public Function SplitPath(path As String) As String()
|
93 |
Return path.Replace("/"c, "\"c) _
|
94 |
.StringReplace("\\{2,}", "\") _
|
95 |
.Trim("\"c) _
|
96 |
.Split("\"c)
|
97 |
End Function
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
<Extension> Public Function Delete(path$, Optional throwEx As Boolean = False) As Boolean
|
106 |
Try
|
107 |
If path.FileExists Then
|
108 |
Call FileIO.FileSystem.DeleteFile(
|
109 |
path, UIOption.OnlyErrorDialogs, RecycleOption.DeletePermanently
|
110 |
)
|
111 |
ElseIf path.DirectoryExists Then
|
112 |
Call FileIO.FileSystem.DeleteDirectory(
|
113 |
path, DeleteDirectoryOption.DeleteAllContents
|
114 |
)
|
115 |
End If
|
116 |
|
117 |
Return True
|
118 |
Catch ex As Exception
|
119 |
If throwEx Then
|
120 |
Throw New Exception(path, ex)
|
121 |
Else
|
122 |
Call App.LogException(ex, path)
|
123 |
End If
|
124 |
|
125 |
Return False
|
126 |
Finally
|
127 |
End Try
|
128 |
End Function
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
136 |
<Extension>
|
137 |
Public Function ExtensionSuffix(path$) As String
|
138 |
If path.StringEmpty Then
|
139 |
Return ""
|
140 |
Else
|
141 |
Return path.Split("."c).Last
|
142 |
End If
|
143 |
End Function
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
161 |
<Extension>
|
162 |
Public Function DIR(d As DirectoryInfo, name$) As String
|
163 |
Return $"{d.FullName}/{name}"
|
164 |
End Function
|
165 |
|
166 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
167 |
<Extension>
|
168 |
Public Function UnixPath(path As String) As String
|
169 |
Return FileIO.FileSystem.GetFileInfo(path).FullName.Replace("\", "/")
|
170 |
End Function
|
171 |
|
172 |
|
173 |
|
174 |
|
175 |
|
176 |
<Extension> Public Sub MkDIR(DIR$, Optional throwEx As Boolean = True)
|
177 |
If DIR.StringEmpty OrElse DIR = "./" OrElse DIR = ".\" Then
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
DIR = App.CurrentDirectory
|
184 |
End If
|
185 |
|
186 |
Try
|
187 |
Call FileIO.FileSystem.CreateDirectory(DIR)
|
188 |
Catch ex As Exception
|
189 |
ex = New Exception("DIR value is: " & DIR, ex)
|
190 |
|
191 |
If throwEx Then
|
192 |
Throw ex
|
193 |
Else
|
194 |
Call App.LogException(ex)
|
195 |
End If
|
196 |
End Try
|
197 |
End Sub
|
198 |
|
199 |
<Extension>
|
200 |
Public Function PathCombine(path As String, addTag As String) As String
|
201 |
If path.DirectoryExists Then
|
202 |
Return path.ParentPath & "/" & path.BaseName & addTag
|
203 |
Else
|
204 |
Return path.TrimSuffix & addTag
|
205 |
End If
|
206 |
End Function
|
207 |
|
208 |
ReadOnly allKinds As New DefaultValue(Of String())({"*.*"}, Function(o) TryCast(o, String()).IsNullOrEmpty)
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
<Extension>
|
222 |
Public Function EnumerateFiles(DIR$, ParamArray keyword$()) As IEnumerable(Of String)
|
223 |
Return FileIO.FileSystem.GetFiles(DIR, FileIO.SearchOption.SearchTopLevelOnly, keyword Or allKinds)
|
224 |
End Function
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
237 |
<Extension>
|
238 |
Public Function ListFiles(DIR$, Optional pattern$ = "*.*") As IEnumerable(Of String)
|
239 |
Return ls - l - r - pattern <= DIR
|
240 |
End Function
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 |
<Extension>
|
249 |
Public Iterator Function ReadDirectory(DIR$, Optional [option] As FileIO.SearchOption = FileIO.SearchOption.SearchTopLevelOnly) As IEnumerable(Of String)
|
250 |
Dim current As New DirectoryInfo(DIR)
|
251 |
|
252 |
For Each file In current.EnumerateFiles
|
253 |
Yield file.FullName
|
254 |
Next
|
255 |
|
256 |
If [option] = FileIO.SearchOption.SearchAllSubDirectories Then
|
257 |
For Each folder In current.EnumerateDirectories
|
258 |
For Each path In folder.FullName.ReadDirectory([option])
|
259 |
Yield path
|
260 |
Next
|
261 |
Next
|
262 |
End If
|
263 |
End Function
|
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 |
<Extension>
|
272 |
Public Iterator Function ListDirectory(DIR$, Optional [option] As FileIO.SearchOption = FileIO.SearchOption.SearchTopLevelOnly) As IEnumerable(Of String)
|
273 |
Dim current As New DirectoryInfo(DIR)
|
274 |
|
275 |
For Each folder In current.EnumerateDirectories
|
276 |
Yield folder.FullName
|
277 |
|
278 |
If [option] = FileIO.SearchOption.SearchAllSubDirectories Then
|
279 |
For Each path In folder.FullName.ListDirectory([option])
|
280 |
Yield path
|
281 |
Next
|
282 |
End If
|
283 |
Next
|
284 |
End Function
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 |
|
291 |
|
292 |
|
293 |
<Extension>
|
294 |
Public Function TheFile(DIR$, keyword$, Optional opt As FileIO.SearchOption = FileIO.SearchOption.SearchTopLevelOnly) As String
|
295 |
If Not DIR.DirectoryExists Then
|
296 |
Return Nothing
|
297 |
End If
|
298 |
Return FileIO.FileSystem.GetFiles(DIR, opt, keyword).FirstOrDefault
|
299 |
End Function
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 |
|
307 |
|
308 |
<ExportAPI("Path2Url", Info:="Gets the URL type file path.")>
|
309 |
<Extension> Public Function ToFileURL(path As String) As String
|
310 |
If String.IsNullOrEmpty(path) Then
|
311 |
Return ""
|
312 |
Else
|
313 |
path = FileIO.FileSystem.GetFileInfo(path).FullName
|
314 |
Return String.Format("file:///{0}", path.Replace("\", "/"))
|
315 |
End If
|
316 |
End Function
|
317 |
|
318 |
<ExportAPI("DIR2URL"), ExtensionAttribute>
|
319 |
Public Function ToDIR_URL(DIR As String) As String
|
320 |
If String.IsNullOrEmpty(DIR) Then
|
321 |
Return ""
|
322 |
Else
|
323 |
DIR = FileIO.FileSystem.GetDirectoryInfo(DIR).FullName
|
324 |
Return String.Format("file:///{0}", DIR.Replace("\", "/"))
|
325 |
End If
|
326 |
End Function
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 |
Public Const ILLEGAL_PATH_CHARACTERS_ENUMERATION As String = ":*?""<>|&"
|
333 |
Public Const ILLEGAL_FILENAME_CHARACTERS As String = "\" & ILLEGAL_PATH_CHARACTERS_ENUMERATION
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 |
<ExportAPI("NormalizePathString")>
|
343 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
344 |
<Extension> Public Function NormalizePathString(str$, Optional OnlyASCII As Boolean = True) As String
|
345 |
Return NormalizePathString(str, "_", OnlyASCII)
|
346 |
End Function
|
347 |
|
348 |
<ExportAPI("NormalizePathString")>
|
349 |
<Extension> Public Function NormalizePathString(str$, normAs As String, Optional onlyASCII As Boolean = True) As String
|
350 |
Dim sb As New StringBuilder(str)
|
351 |
For Each ch As Char In ILLEGAL_FILENAME_CHARACTERS
|
352 |
Call sb.Replace(ch, normAs)
|
353 |
Next
|
354 |
|
355 |
If onlyASCII Then
|
356 |
For Each ch As Char In "()[]+-~!@#$%^&=;',"
|
357 |
Call sb.Replace(ch, normAs)
|
358 |
Next
|
359 |
End If
|
360 |
|
361 |
Return sb.ToString
|
362 |
End Function
|
363 |
|
364 |
Const PathTooLongException =
|
365 |
"System.IO.PathTooLongException: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."
|
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 |
|
376 |
<Extension> Public Function Long2Short(path As String, <CallerMemberName> Optional caller As String = "") As String
|
377 |
Dim parent As String = path.ParentPath
|
378 |
Dim DIRTokens As String() = parent.Replace("\", "/").Split("/"c)
|
379 |
|
380 |
Dim DIRname As String = DIRTokens.Last
|
381 |
|
382 |
Dim name As String = path.Replace("\", "/").Split("/"c).Last
|
383 |
|
384 |
If parent.Length + name.Length >= 259 Then
|
385 |
DIRname = Mid(DIRname, 1, 20) & "~"
|
386 |
Dim ext As String = name.Split("."c).Last
|
387 |
name = Mid(name, 1, 20) & "~." & ext
|
388 |
parent = String.Join("/", DIRTokens.Take(DIRTokens.Length - 1).ToArray)
|
389 |
parent &= "/" & DIRname
|
390 |
parent &= "/" & name
|
391 |
|
392 |
Dim ex As Exception = New PathTooLongException(PathTooLongException)
|
393 |
ex = New Exception(path, ex)
|
394 |
ex = New Exception("But the path was corrected as: " & parent & " to avoid the crashed problem.", ex)
|
395 |
Call ex.PrintException
|
396 |
Call App.LogException(ex, caller & " -> " & MethodBase.GetCurrentMethod.GetFullName)
|
397 |
|
398 |
Return parent.Replace("\", "/")
|
399 |
Else
|
400 |
Return FileIO.FileSystem.GetFileInfo(path).FullName
|
401 |
End If
|
402 |
End Function
|
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
|
409 |
|
410 |
Const DriveLabel$ = "[a-zA-Z]([a-zA-Z0-9])*"
|
411 |
|
412 |
|
413 |
|
414 |
|
415 |
|
416 |
|
417 |
<ExportAPI("Path.Illegal?")>
|
418 |
<Extension> Public Function PathIllegal(path As String) As Boolean
|
419 |
Dim tokens$() = Strings.Split(path.Replace("\", "/"), ":/")
|
420 |
|
421 |
If tokens.Length > 2 Then
|
422 |
Return False
|
423 |
ElseIf tokens.Length = 2 Then
|
424 |
|
425 |
|
426 |
If Not tokens(0).IsPattern(DriveLabel, RegexICSng) Then
|
427 |
|
428 |
Return False
|
429 |
Else
|
430 |
|
431 |
End If
|
432 |
Else
|
433 |
|
434 |
End If
|
435 |
|
436 |
Dim fileName As String = tokens.Last
|
437 |
|
438 |
|
439 |
For Each ch As Char In ILLEGAL_PATH_CHARACTERS_ENUMERATION
|
440 |
If fileName.IndexOf(ch) > -1 Then
|
441 |
Return True
|
442 |
End If
|
443 |
Next
|
444 |
|
445 |
Return False
|
446 |
End Function
|
447 |
|
448 |
|
449 |
|
450 |
|
451 |
|
452 |
|
453 |
|
454 |
<Extension>
|
455 |
Public Function FileLength(path As String) As Long
|
456 |
If Not path.FileExists Then
|
457 |
Return -1&
|
458 |
Else
|
459 |
Return FileIO.FileSystem.GetFileInfo(path).Length
|
460 |
End If
|
461 |
End Function
|
462 |
|
463 |
|
464 |
|
465 |
|
466 |
|
467 |
|
468 |
|
469 |
|
470 |
|
471 |
|
472 |
|
473 |
|
474 |
|
475 |
|
476 |
|
477 |
|
478 |
|
479 |
|
480 |
|
481 |
<Extension> Public Function FileCopy(source$, copyTo$) As Boolean
|
482 |
Try
|
483 |
If copyTo.Last = "/"c OrElse copyTo.Last = "\"c Then
|
484 |
copyTo = copyTo & source.FileName
|
485 |
End If
|
486 |
|
487 |
If copyTo.FileExists Then
|
488 |
Call FileIO.FileSystem.DeleteFile(copyTo)
|
489 |
Else
|
490 |
Call copyTo.ParentPath.MkDIR
|
491 |
End If
|
492 |
|
493 |
Call FileIO.FileSystem.CopyFile(source, copyTo)
|
494 |
Catch ex As Exception
|
495 |
ex = New Exception({source, copyTo}.GetJson, ex)
|
496 |
App.LogException(ex)
|
497 |
|
498 |
Return False
|
499 |
End Try
|
500 |
|
501 |
Return True
|
502 |
End Function
|
503 |
|
504 |
<Extension>
|
505 |
Public Function FileMove(source$, target$) As Boolean
|
506 |
Try
|
507 |
Call My.Computer.FileSystem.MoveFile(source, target)
|
508 |
Return True
|
509 |
Catch ex As Exception
|
510 |
ex = New Exception("source: " & source, ex)
|
511 |
ex = New Exception("target: " & target, ex)
|
512 |
|
513 |
Call App.LogException(ex)
|
514 |
|
515 |
Return False
|
516 |
End Try
|
517 |
End Function
|
518 |
|
519 |
|
520 |
|
521 |
|
522 |
|
523 |
|
524 |
|
525 |
|
526 |
|
527 |
#If FRAMEWORD_CORE Then
|
528 |
<ExportAPI("File.Exists", Info:="Check if the target file object is exists on your file system or not.")>
|
529 |
<Extension> Public Function FileExists(path$, Optional ZERO_Nonexists As Boolean = False) As Boolean
|
530 |
#Else
|
531 |
<Extension> Public Function FileExists(path As String) As Boolean
|
532 |
#End If
|
533 |
|
534 |
If path.StringEmpty Then
|
535 |
Return False
|
536 |
End If
|
537 |
If path.IndexOf(ASCII.CR) > -1 OrElse path.IndexOf(ASCII.LF) > -1 Then
|
538 |
Return False
|
539 |
End If
|
540 |
|
541 |
If Not String.IsNullOrEmpty(path) AndAlso
|
542 |
FileIO.FileSystem.FileExists(path) Then
|
543 |
|
544 |
If ZERO_Nonexists Then
|
545 |
Return FileSystem.FileLen(path) > 0
|
546 |
Else
|
547 |
Return True
|
548 |
End If
|
549 |
Else
|
550 |
Return False
|
551 |
End If
|
552 |
End Function
|
553 |
|
554 |
|
555 |
|
556 |
|
557 |
|
558 |
|
559 |
<ExportAPI("DIR.Exists", Info:="Determine that the target directory is exists on the file system or not?")>
|
560 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
561 |
<Extension>
|
562 |
Public Function DirectoryExists(DIR As String) As Boolean
|
563 |
Return Not String.IsNullOrEmpty(DIR) AndAlso
|
564 |
FileIO.FileSystem.DirectoryExists(DIR)
|
565 |
End Function
|
566 |
|
567 |
|
568 |
|
569 |
|
570 |
|
571 |
|
572 |
|
573 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
574 |
<Extension> Public Function DirectoryName(dir$) As String
|
575 |
Return dir.TrimDIR _
|
576 |
.Split("\"c).Last _
|
577 |
.Split("/"c).Last
|
578 |
End Function
|
579 |
|
580 |
|
581 |
|
582 |
|
583 |
|
584 |
|
585 |
|
586 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
587 |
<ExportAPI("File.IsOpened", Info:="Detect while the target file is opened by someone process.")>
|
588 |
<Extension> Public Function FileOpened(FileName As String) As Boolean
|
589 |
Try
|
590 |
Using FileOpenDetect As New FileStream(
|
591 |
path:=FileName,
|
592 |
mode:=FileMode.Open,
|
593 |
access:=FileAccess.Read,
|
594 |
share:=FileShare.None
|
595 |
)
|
596 |
|
597 |
End Using
|
598 |
|
599 |
Return True
|
600 |
Catch ex As Exception
|
601 |
Return False
|
602 |
End Try
|
603 |
End Function
|
604 |
|
605 |
|
606 |
|
607 |
|
608 |
|
609 |
|
610 |
|
611 |
|
612 |
|
613 |
|
614 |
|
615 |
|
616 |
|
617 |
|
618 |
<ExportAPI(NameOf(BaseName), Info:="Gets the name of the target directory/file object.")>
|
619 |
<Extension> Public Function BaseName(fsObj$, Optional allowEmpty As Boolean = False) As String
|
620 |
If fsObj.StringEmpty Then
|
621 |
If allowEmpty Then
|
622 |
Return ""
|
623 |
Else
|
624 |
Throw New NullReferenceException(NameOf(fsObj) & " file system object handle is null!")
|
625 |
End If
|
626 |
End If
|
627 |
|
628 |
|
629 |
Dim t$() = fsObj.Trim("\"c, "/"c) _
|
630 |
.Replace("\", "/") _
|
631 |
.Split("/"c) _
|
632 |
.Last _
|
633 |
.Split("."c)
|
634 |
|
635 |
If t.Length > 1 Then
|
636 |
|
637 |
|
638 |
t = t.Take(t.Length - 1) _
|
639 |
.ToArray
|
640 |
End If
|
641 |
|
642 |
Dim name = String.Join(".", t)
|
643 |
Return name
|
644 |
End Function
|
645 |
|
646 |
|
647 |
|
648 |
|
649 |
|
650 |
|
651 |
|
652 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
653 |
<Extension> Public Function GetBaseName(path As String) As String
|
654 |
Return BaseName(path)
|
655 |
End Function
|
656 |
|
657 |
|
658 |
|
659 |
|
660 |
|
661 |
|
662 |
|
663 |
<Extension> Public Function ParentDirName(file As String) As String
|
664 |
Dim parentDir As String = FileIO.FileSystem.GetParentPath(file)
|
665 |
Dim parDirInfo = FileIO.FileSystem.GetDirectoryInfo(parentDir)
|
666 |
Return parDirInfo.Name
|
667 |
End Function
|
668 |
|
669 |
|
670 |
|
671 |
|
672 |
|
673 |
|
674 |
|
675 |
|
676 |
|
677 |
<ExportAPI(NameOf(ParentPath))>
|
678 |
<Extension> Public Function ParentPath(file$, Optional full As Boolean = True) As String
|
679 |
file = file.Replace("\", "/")
|
680 |
|
681 |
Dim parent As String = ""
|
682 |
Dim t As String() = file.Split("/"c)
|
683 |
|
684 |
If full Then
|
685 |
If InStr(file, "../") = 1 Then
|
686 |
parent = FileIO.FileSystem.GetParentPath(App.CurrentDirectory)
|
687 |
t = t.Skip(1).ToArray
|
688 |
parent &= "/"
|
689 |
ElseIf InStr(file, "./") = 1 Then
|
690 |
parent = App.CurrentDirectory
|
691 |
t = t.Skip(1).ToArray
|
692 |
parent &= "/"
|
693 |
Else
|
694 |
|
695 |
End If
|
696 |
|
697 |
If file.Last = "/"c Then
|
698 |
parent &= String.Join("/", t.Take(t.Length - 2).ToArray)
|
699 |
Else
|
700 |
parent &= String.Join("/", t.Take(t.Length - 1).ToArray)
|
701 |
End If
|
702 |
|
703 |
If parent.StringEmpty Then
|
704 |
|
705 |
parent = App.CurrentDirectory
|
706 |
End If
|
707 |
Else
|
708 |
parent = String.Join("/", t.Take(t.Length - 1).ToArray)
|
709 |
End If
|
710 |
|
711 |
Return parent
|
712 |
End Function
|
713 |
|
714 |
|
715 |
|
716 |
|
717 |
|
718 |
|
719 |
|
720 |
|
721 |
|
722 |
|
723 |
<ExportAPI("Get.File.Path")>
|
724 |
<Extension> Public Function GetFile(DIR As String,
|
725 |
<Parameter("Using.Keyword")> keyword As String,
|
726 |
<Parameter("List.Ext")> ParamArray ext As String()) _
|
727 |
As <FunctionReturns("A list of file path which match with the keyword and the file extension name.")> String()
|
728 |
|
729 |
Dim Files As IEnumerable(Of String) = ls - l - wildcards(ext) <= DIR
|
730 |
Dim matches = (From Path As String
|
731 |
In Files.AsParallel
|
732 |
Let NameID = BaseName(Path)
|
733 |
Where InStr(NameID, keyword, CompareMethod.Text) > 0
|
734 |
Let ExtValue = Path.Split("."c).Last
|
735 |
Select Path,
|
736 |
ExtValue)
|
737 |
Dim LQuery =
|
738 |
From extType As String
|
739 |
In ext
|
740 |
Select From path
|
741 |
In matches
|
742 |
Where InStr(extType, path.ExtValue, CompareMethod.Text) > 0
|
743 |
Select path.Path
|
744 |
Return LQuery.IteratesALL.Distinct.ToArray
|
745 |
End Function
|
746 |
|
747 |
|
748 |
|
749 |
|
750 |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 |
|
756 |
<ExportAPI("Load.ResourceEntry",
|
757 |
Info:="Load the file from a specific directory from the source parameter as the resource entry list.")>
|
758 |
<Extension>
|
759 |
Public Function LoadSourceEntryList(<Parameter("Dir.Source", "The source directory which will be searchs for file.")> source As String,
|
760 |
<Parameter("List.Ext", "The list of the file extension.")> ext As String(),
|
761 |
Optional topLevel As Boolean = True) As Dictionary(Of String, String)
|
762 |
|
763 |
If ext.IsNullOrEmpty Then
|
764 |
ext = {"*.*"}
|
765 |
End If
|
766 |
|
767 |
Dim LQuery = (From path As String
|
768 |
In If(topLevel, ls - l, ls - l - r) - wildcards(ext) <= source
|
769 |
Select ID = BaseName(path),
|
770 |
path
|
771 |
Group By ID Into Group).ToArray
|
772 |
|
773 |
ext = LinqAPI.Exec(Of String) <= From value As String
|
774 |
In ext
|
775 |
Select value.Split(CChar(".")).Last.ToLower
|
776 |
|
777 |
Dim res As Dictionary(Of String, String) = LQuery _
|
778 |
.ToDictionary(Function(x) x.ID,
|
779 |
Function(x)
|
780 |
|
781 |
Return LinqAPI.DefaultFirst(Of String) _
|
782 |
_
|
783 |
() <= From path
|
784 |
In x.Group
|
785 |
Let pathValue = path.path
|
786 |
Let extValue As String = pathValue.Split("."c).Last.ToLower
|
787 |
Where Array.IndexOf(ext, extValue) > -1
|
788 |
Select pathValue
|
789 |
|
790 |
End Function)
|
791 |
|
792 |
With From entry
|
793 |
In res
|
794 |
Where Not String.IsNullOrEmpty(entry.Value)
|
795 |
Select entry
|
796 |
|
797 |
res = .ToDictionary(Function(x) x.Key,
|
798 |
Function(x) x.Value)
|
799 |
End With
|
800 |
|
801 |
Call $"{NameOf(ProgramPathSearchTool)} load {res.Count} source entry...".__DEBUG_ECHO
|
802 |
|
803 |
Return res
|
804 |
End Function
|
805 |
|
806 |
|
807 |
|
808 |
|
809 |
|
810 |
|
811 |
|
812 |
|
813 |
|
814 |
<Extension> Public Function LoadSourceEntryList(source$, ParamArray ext$()) As Dictionary(Of String, String)
|
815 |
If Not FileIO.FileSystem.DirectoryExists(source) Then
|
816 |
Return New Dictionary(Of String, String)
|
817 |
End If
|
818 |
|
819 |
Dim LQuery = From path As String
|
820 |
In FileIO.FileSystem.GetFiles(source, FileIO.SearchOption.SearchAllSubDirectories, ext)
|
821 |
Select ID = BaseName(path),
|
822 |
path
|
823 |
Group By ID Into Group
|
824 |
Dim dict As Dictionary(Of String, String) =
|
825 |
LQuery.ToDictionary(Function(x) x.ID,
|
826 |
Function(x) x.Group.First.path)
|
827 |
Return dict
|
828 |
End Function
|
829 |
|
830 |
|
831 |
|
832 |
|
833 |
|
834 |
|
835 |
|
836 |
|
837 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
838 |
<ExportAPI("Load.ResourceEntry")>
|
839 |
<Extension> Public Function LoadEntryList(<Parameter("Dir.Source")> DIR$, ParamArray exts$()) As NamedValue(Of String)()
|
840 |
Return LinqAPI.Exec(Of NamedValue(Of String)) _
|
841 |
_
|
842 |
() <= From path As String
|
843 |
In ls - l - ShellSyntax.r - wildcards(exts) <= DIR
|
844 |
Select New NamedValue(Of String) With {
|
845 |
.Name = path.BaseName,
|
846 |
.Value = path
|
847 |
}
|
848 |
|
849 |
End Function
|
850 |
|
851 |
<ExportAPI("Load.ResourceEntry", Info:="Load the file from a specific directory from the source parameter as the resource entry list.")>
|
852 |
<Extension>
|
853 |
Public Function LoadSourceEntryList(source As IEnumerable(Of String)) As Dictionary(Of String, String)
|
854 |
Dim LQuery = From path As String
|
855 |
In source
|
856 |
Select ID = BaseName(path),
|
857 |
path
|
858 |
Group By ID Into Group
|
859 |
Dim res As Dictionary(Of String, String) =
|
860 |
LQuery.ToDictionary(Function(x) x.ID,
|
861 |
Function(x) x.Group.First.path)
|
862 |
Return res
|
863 |
End Function
|
864 |
|
865 |
|
866 |
|
867 |
|
868 |
|
869 |
|
870 |
|
871 |
|
872 |
<ExportAPI("Source.Copy",
|
873 |
Info:="Copy the file in the source list into the copyto directory, function returns the failed operation list.")>
|
874 |
Public Function SourceCopy(source As IEnumerable(Of String), CopyTo As String, Optional [Overrides] As Boolean = False) As String()
|
875 |
Dim failedList As New List(Of String)
|
876 |
|
877 |
For Each file As String In source
|
878 |
Try
|
879 |
Call FileIO.FileSystem.CopyFile(file, CopyTo & "/" & FileIO.FileSystem.GetFileInfo(file).Name, [Overrides])
|
880 |
Catch ex As Exception
|
881 |
Call failedList.Add(file)
|
882 |
Call App.LogException(New Exception(file, ex))
|
883 |
End Try
|
884 |
Next
|
885 |
|
886 |
Return failedList.ToArray
|
887 |
End Function
|
888 |
|
889 |
<ExportAPI("Get.FrequentPath",
|
890 |
Info:="Gets a directory path which is most frequent appeared in the file list.")>
|
891 |
Public Function GetMostAppreancePath(files As IEnumerable(Of String)) As String
|
892 |
If files Is Nothing Then
|
893 |
Return ""
|
894 |
End If
|
895 |
|
896 |
Dim LQuery = From strPath As String
|
897 |
In files
|
898 |
Select FileIO.FileSystem.GetParentPath(strPath)
|
899 |
Return LQuery _
|
900 |
.TokenCount(ignoreCase:=True) _
|
901 |
.OrderByDescending(Function(x) x.Value) _
|
902 |
.FirstOrDefault _
|
903 |
.Key
|
904 |
End Function
|
905 |
|
906 |
|
907 |
|
908 |
|
909 |
|
910 |
|
911 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
912 |
<ExportAPI(NameOf(RelativePath),
|
913 |
Info:="Get the specific file system object its relative path to the application base directory.")>
|
914 |
Public Function RelativePath(path As String) As String
|
915 |
Return RelativePath(App.HOME, path)
|
916 |
End Function
|
917 |
|
918 |
|
919 |
|
920 |
|
921 |
|
922 |
|
923 |
|
924 |
|
925 |
|
926 |
<ExportAPI(NameOf(RelativePath),
|
927 |
Info:="Gets the relative path value of pcTo file system object relative to a reference directory pcFrom")>
|
928 |
Public Function RelativePath(pcFrom$, pcTo$,
|
929 |
Optional appendParent As Boolean = True,
|
930 |
Optional fixZipPath As Boolean = False) As <FunctionReturns("The relative path string of pcTo file object reference to directory pcFrom")> String
|
931 |
|
932 |
Dim lcRelativePath As String = Nothing
|
933 |
Dim lcFrom As String = (If(pcFrom Is Nothing, "", pcFrom.Trim().Replace("\", "/")))
|
934 |
Dim lcTo As String = (If(pcTo Is Nothing, "", pcTo.Trim().Replace("\", "/")))
|
935 |
|
936 |
If lcFrom.Length = 0 OrElse lcTo.Length = 0 Then
|
937 |
Throw New InvalidDataException("One of the path string value is null!")
|
938 |
End If
|
939 |
If Not IO.Path.GetPathRoot(lcFrom.ToUpper()) _
|
940 |
.Equals(IO.Path.GetPathRoot(lcTo.ToUpper())) Then
|
941 |
Return pcTo
|
942 |
End If
|
943 |
|
944 |
|
945 |
|
946 |
Dim laDirSep As Char() = {"\"c}
|
947 |
Dim lcPathFrom As String = (If(IO.Path.GetDirectoryName(lcFrom) Is Nothing, IO.Path.GetPathRoot(lcFrom.ToUpper()), IO.Path.GetDirectoryName(lcFrom)))
|
948 |
Dim lcPathTo As String = (If(IO.Path.GetDirectoryName(lcTo) Is Nothing, IO.Path.GetPathRoot(lcTo.ToUpper()), IO.Path.GetDirectoryName(lcTo)))
|
949 |
Dim lcFileTo As String = (If(IO.Path.GetFileName(lcTo) Is Nothing, "", IO.Path.GetFileName(lcTo)))
|
950 |
Dim laFrom As String() = lcPathFrom.Split(laDirSep)
|
951 |
Dim laTo As String() = lcPathTo.Split(laDirSep)
|
952 |
Dim lnFromCnt As Integer = laFrom.Length
|
953 |
Dim lnToCnt As Integer = laTo.Length
|
954 |
Dim lnSame As Integer = 0
|
955 |
Dim lnCount As Integer = 0
|
956 |
|
957 |
While lnToCnt > 0 AndAlso lnSame < lnToCnt
|
958 |
If lnCount < lnFromCnt Then
|
959 |
If laFrom(lnCount).ToUpper().Equals(laTo(lnCount).ToUpper()) Then
|
960 |
lnSame += 1
|
961 |
Else
|
962 |
Exit While
|
963 |
End If
|
964 |
Else
|
965 |
Exit While
|
966 |
End If
|
967 |
lnCount += 1
|
968 |
End While
|
969 |
|
970 |
Dim lcEndPart As String = ""
|
971 |
For lnEnd As Integer = lnSame To lnToCnt - 1
|
972 |
If laTo(lnEnd).Length > 0 Then
|
973 |
lcEndPart += laTo(lnEnd) & "\"
|
974 |
Else
|
975 |
Exit For
|
976 |
End If
|
977 |
Next
|
978 |
|
979 |
Dim lnDiff As Integer = Abs(lnFromCnt - lnSame)
|
980 |
If lnDiff > 0 AndAlso laFrom(lnFromCnt - 1).Length > 0 Then
|
981 |
While lnDiff > 0
|
982 |
lnDiff -= 1
|
983 |
lcEndPart = "..\" & lcEndPart
|
984 |
End While
|
985 |
End If
|
986 |
|
987 |
lcRelativePath = lcEndPart & lcFileTo
|
988 |
|
989 |
If appendParent Then
|
990 |
Return "..\" & lcRelativePath
|
991 |
Else
|
992 |
If fixZipPath Then
|
993 |
|
994 |
|
995 |
Return lcRelativePath _
|
996 |
.Split("\"c) _
|
997 |
.Skip(1) _
|
998 |
.JoinBy("\")
|
999 |
Else
|
1000 |
Return lcRelativePath
|
1001 |
End If
|
1002 |
End If
|
1003 |
End Function
|
1004 |
|
1005 |
|
1006 |
|
1007 |
|
1008 |
|
1009 |
|
1010 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
1011 |
<ExportAPI("File.FullPath", Info:="Gets the full path of the file.")>
|
1012 |
<Extension> Public Function GetFullPath(file As String) As String
|
1013 |
Return FileIO.FileSystem.GetFileInfo(file).FullName.Replace("\", "/")
|
1014 |
End Function
|
1015 |
|
1016 |
|
1017 |
|
1018 |
|
1019 |
|
1020 |
|
1021 |
|
1022 |
|
1023 |
<ExportAPI("Dir.FullPath", Info:="Gets the full path of the directory.")>
|
1024 |
<Extension> Public Function GetDirectoryFullPath(dir$, <CallerMemberName> Optional stack$ = Nothing) As String
|
1025 |
Try
|
1026 |
Return FileIO.FileSystem _
|
1027 |
.GetDirectoryInfo(dir) _
|
1028 |
.FullName _
|
1029 |
.Replace("\", "/")
|
1030 |
Catch ex As Exception
|
1031 |
stack = stack & " --> " & NameOf(GetDirectoryFullPath)
|
1032 |
|
1033 |
If dir = "/" AndAlso Not App.IsMicrosoftPlatform Then
|
1034 |
Return "/"
|
1035 |
Else
|
1036 |
ex = New Exception(stack & ": " & dir, ex)
|
1037 |
Call App.LogException(ex)
|
1038 |
Call ex.PrintException
|
1039 |
Return dir
|
1040 |
End If
|
1041 |
End Try
|
1042 |
End Function
|
1043 |
|
1044 |
|
1045 |
|
1046 |
|
1047 |
|
1048 |
|
1049 |
<ExportAPI("File.Ext.Trim")>
|
1050 |
<Extension> Public Function TrimSuffix(file As String) As String
|
1051 |
Try
|
1052 |
Dim path$ = file.FixPath.TrimEnd("/"c, "\"c)
|
1053 |
Dim fileInfo = FileIO.FileSystem.GetFileInfo(path$)
|
1054 |
Dim Name As String = BaseName(fileInfo.FullName)
|
1055 |
Return $"{fileInfo.Directory.FullName}/{Name}"
|
1056 |
Catch ex As Exception
|
1057 |
ex = New Exception($"{NameOf(file)} --> {file}", ex)
|
1058 |
Throw ex
|
1059 |
End Try
|
1060 |
End Function
|
1061 |
|
1062 |
|
1063 |
|
1064 |
|
1065 |
|
1066 |
|
1067 |
|
1068 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
1069 |
<Extension>
|
1070 |
Public Function TrimDIR(DIR As String) As String
|
1071 |
Return DIR.TrimEnd("/"c, "\"c)
|
1072 |
End Function
|
1073 |
|
1074 |
|
1075 |
|
1076 |
|
1077 |
|
1078 |
|
1079 |
|
1080 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
1081 |
<ExportAPI("File.Name")>
|
1082 |
<Extension>
|
1083 |
Public Function FileName(path As String) As String
|
1084 |
Try
|
1085 |
Return FileIO.FileSystem.GetFileInfo(path).Name
|
1086 |
Catch ex As Exception
|
1087 |
Throw New InvalidOperationException(path, ex)
|
1088 |
End Try
|
1089 |
End Function
|
1090 |
|
1091 |
|
1092 |
|
1093 |
|
1094 |
|
1095 |
|
1096 |
|
1097 |
<ExportAPI("SafeCopyTo")>
|
1098 |
Public Function SafeCopyTo(source As String, copyTo As String) As Boolean
|
1099 |
Try
|
1100 |
Dim buf As Byte() = IO.File.ReadAllBytes(source)
|
1101 |
Call buf.FlushStream(copyTo)
|
1102 |
Catch ex As Exception
|
1103 |
Dim pt As String = $"{source.ToFileURL} ===> {copyTo.ToFileURL}"
|
1104 |
Call App.LogException(New Exception(pt, ex))
|
1105 |
Return False
|
1106 |
End Try
|
1107 |
|
1108 |
Return True
|
1109 |
End Function
|
1110 |
End Module
|