From c0e7fddd5e597a2714ee76d7c571271c164b4390 Mon Sep 17 00:00:00 2001 From: sharpchen Date: Tue, 21 Jan 2025 00:11:26 +0800 Subject: [PATCH] main --- .../PowerShell/docs/File System/1.Overview.md | 9 -- .../docs/File System/3.Special Folders.md | 19 --- .../2.Working Directory.md | 0 .../4.Manipulate Item.md | 0 .../5.Write to File.md | 0 .../6.Inspect File System.md | 0 .../File Size.md | 0 .../PowerShell/docs/Item Manipulation/Path.md | 101 +++++++++++++++ .../PowerShell/docs/Language/Control Flow.md | 120 +++++++++++++++++- .../docs/Standard IO/Stream Redirection.md | 42 ++++++ docs/document/PowerShell/docs/Terminology.md | 10 ++ 11 files changed, 271 insertions(+), 30 deletions(-) delete mode 100644 docs/document/PowerShell/docs/File System/1.Overview.md delete mode 100644 docs/document/PowerShell/docs/File System/3.Special Folders.md rename docs/document/PowerShell/docs/{File System => Item Manipulation}/2.Working Directory.md (100%) rename docs/document/PowerShell/docs/{File System => Item Manipulation}/4.Manipulate Item.md (100%) rename docs/document/PowerShell/docs/{File System => Item Manipulation}/5.Write to File.md (100%) rename docs/document/PowerShell/docs/{File System => Item Manipulation}/6.Inspect File System.md (100%) rename docs/document/PowerShell/docs/{File System => Item Manipulation}/File Size.md (100%) create mode 100644 docs/document/PowerShell/docs/Item Manipulation/Path.md create mode 100644 docs/document/PowerShell/docs/Standard IO/Stream Redirection.md diff --git a/docs/document/PowerShell/docs/File System/1.Overview.md b/docs/document/PowerShell/docs/File System/1.Overview.md deleted file mode 100644 index 2435c0ad..00000000 --- a/docs/document/PowerShell/docs/File System/1.Overview.md +++ /dev/null @@ -1,9 +0,0 @@ -# Overview - -**FileSystem** is a builtin **PSProvider** in Powershell. - -FileSystem can have one or more **PSDrive** depending on the system. - -In windows, drives can be `C:`, `D:` and so on. In linux they can be some mount points. - -This section introduces how to manipulate file system objects with item-related cmdlet. diff --git a/docs/document/PowerShell/docs/File System/3.Special Folders.md b/docs/document/PowerShell/docs/File System/3.Special Folders.md deleted file mode 100644 index f8cadd0b..00000000 --- a/docs/document/PowerShell/docs/File System/3.Special Folders.md +++ /dev/null @@ -1,19 +0,0 @@ -# Special Folders - -## Home Directory - -- `$HOME` -- `$env:USERPROFILE` - -## Temp Folder - -- `$env:TMP` -- `$env:TEMP` - -## APPDATA - -- `$env:APPDATA` - -## LOCALAPPDATA - -- `$env:LOCALAPPDATA` diff --git a/docs/document/PowerShell/docs/File System/2.Working Directory.md b/docs/document/PowerShell/docs/Item Manipulation/2.Working Directory.md similarity index 100% rename from docs/document/PowerShell/docs/File System/2.Working Directory.md rename to docs/document/PowerShell/docs/Item Manipulation/2.Working Directory.md diff --git a/docs/document/PowerShell/docs/File System/4.Manipulate Item.md b/docs/document/PowerShell/docs/Item Manipulation/4.Manipulate Item.md similarity index 100% rename from docs/document/PowerShell/docs/File System/4.Manipulate Item.md rename to docs/document/PowerShell/docs/Item Manipulation/4.Manipulate Item.md diff --git a/docs/document/PowerShell/docs/File System/5.Write to File.md b/docs/document/PowerShell/docs/Item Manipulation/5.Write to File.md similarity index 100% rename from docs/document/PowerShell/docs/File System/5.Write to File.md rename to docs/document/PowerShell/docs/Item Manipulation/5.Write to File.md diff --git a/docs/document/PowerShell/docs/File System/6.Inspect File System.md b/docs/document/PowerShell/docs/Item Manipulation/6.Inspect File System.md similarity index 100% rename from docs/document/PowerShell/docs/File System/6.Inspect File System.md rename to docs/document/PowerShell/docs/Item Manipulation/6.Inspect File System.md diff --git a/docs/document/PowerShell/docs/File System/File Size.md b/docs/document/PowerShell/docs/Item Manipulation/File Size.md similarity index 100% rename from docs/document/PowerShell/docs/File System/File Size.md rename to docs/document/PowerShell/docs/Item Manipulation/File Size.md diff --git a/docs/document/PowerShell/docs/Item Manipulation/Path.md b/docs/document/PowerShell/docs/Item Manipulation/Path.md new file mode 100644 index 00000000..94a5a597 --- /dev/null +++ b/docs/document/PowerShell/docs/Item Manipulation/Path.md @@ -0,0 +1,101 @@ +# Path + +## Resolve Path + +- `-Path(0, pv)`: expand path containing special characters like `~` or UNC(Universal Naming Convention) path and some other special paths + ```ps1 + Resolve-Path '~/*' # returns all PathInfo of children under `~` + Resolve-Path ~ # returns expanded path as PathInfo of `~` + ``` +- `-Relative(switch)`: get all relative paths from current path or specified location of items to be listed + ```ps1 + Resolve-Path '~/*' -Relative # list all relative string of children under ~ relative to current location + ``` +- `-RelativeBasePath`: get all relative paths from specified location of items to be listed + ```ps1 + Resolve-Path '~/*' -RelativeBasePath ~ -Relative # list all children of ~ relative to ~ itself + ``` + +## Part of Path + +- `-Path(0, pv)`: get parent path as `PathInfo` + ```ps1 + Split-Path ([System.IO.Path]::GetTempFileName()) # C:\Users\username\AppData\Local\Temp + ``` +- `-Parent(!, switch)`: optional, the default flag for `Split-Path`, returns the parent container of `-Path` +- `-Leaf(switch)`: get base name of a path + ```ps1 + Split-Path ([System.IO.Path]::GetTempFileName()) -Leaf # tmpfigvir.tmp + ``` +- `-LeafBase(switch)`: get base name without extension + ```ps1 + Split-Path ([System.IO.Path]::GetTempFileName()) -LeafBase # tmpfigvir + ``` +- `-Extension(switch)`: get extension + ```ps1 + Split-Path ([System.IO.Path]::GetTempFileName()) -Extension # .tmp + ``` +- `-Qualifier(switch)`: get drive prefix of the path, not available on non-Windows platform + ```ps1 + Split-Path ([System.IO.Path]::GetTempFileName()) -Qualifier # C: + ``` +- `-NoQualifier(switch)`: exclude the drive prefix of the path, not available on non-Windows platform + ```ps1 + Split-Path ([System.IO.Path]::GetTempFileName()) -NoQualifier # \Users\username\AppData\Local\Temp\tmpoo33lr.tmp + ``` +- `-IsAbsolute(switch)`: telling whether the path is absolute +- `-Resolve(switch)`: handles relative or wildcard path for `-Path` + ```ps1 + Split-Path ~/* -Resolve # all parents of children under ~, which are all the same as `Resolve-Path ~` + ``` + +## Path Validation + +- `-Path(0, pv)`: telling whether the path exists, can be relative + ```ps1 + Test-Path '~/.vimrc' + Test-Path '../.gitignore' + ``` +- `-Filter`: common filter + ```ps1 + Test-Path '~/*rc' + ``` +- `-IsValid(switch)`: telling whether the provided path has correct syntax + ```ps1 + Test-Path 'foo/bar' # False + Test-Path 'foo/bar' -IsValid # True + ``` +- `-Exclude` & `-Include`: telling whether any/no path matches the specified pattern + ```ps1 + Test-Path '~/*' -Exclude *rc # is there any file exists besides rc files? + ``` +- `-PathType`: telling whether the path is a leaf or a container(leaf is the child of a container) + ```ps1 + Test-Path '~/.vimrc' -PathType Leaf # True, it is a file indeed + ``` + > [!NOTE] + > The meaning of `Leaf` is not the same as `Leaf` in `Split-Path`, `Leaf` can be any kind of child of a container in `Split-Path`. +- `-NewerThan` & `-OlderThan`: telling whether the path was created before/after a date(can be date string) + ```ps1 + Test-Path ~/.vimrc -NewerThan "2012.6.12" + ``` + +## Join Path + +- `-Path(0)` & `-ChildPath(1)`: join one or more parents with single child + ```ps1 + Join-Path C:, D: foo + # C:\foo + # D:\foo + ``` +- `-AdditionalChildPath(remain)`: accepts unlimited count of child paths + ```ps1 + Join-Path -Path foo -ChildPath foo -AdditionalChildPath foo, foo, foo # this is how it work formally + Join-Path foo foo foo foo foo # this is how you could use it in daily life + ``` +- `-Resolve(switch)`: resolve( and validate) the path and join them, supports wildcard to join multiple matches at one time + ```ps1 + Join-Path ~/Projects nix-config -Resolve # C:\Users\username\Projects\nix-config + Join-Path ~/Projects .git -Resolve # C:\Users\username\Projects\.git does not exist # [!code error] + Join-Path ~/Projects * -Resolve # equvalent to `Resolve-Path ~/Projects/* | % Path` # [!code highlight] + ``` diff --git a/docs/document/PowerShell/docs/Language/Control Flow.md b/docs/document/PowerShell/docs/Language/Control Flow.md index 7b9c1ed8..89e1590a 100644 --- a/docs/document/PowerShell/docs/Language/Control Flow.md +++ b/docs/document/PowerShell/docs/Language/Control Flow.md @@ -105,12 +105,128 @@ It has a few different patterns available: - Regex: matching by regex string, specifically for `string`. - Wildcard: matching by wildcard string, specifically for `string`. +### Synopsis + +`switch` in PowerShell differs from c-like languages in: +- condition can be a procedure(scriptblock) so you can perform more nested and complex determine + ```ps1 + switch (1) { + { $_ -is [int] } { "Int32" } + } + ``` +- can have implicit return, each time the case matches yields the result into the final array, or just the singular result when only one case matches + ```ps1 + $foo = switch ($bar) { <# ... #> } + $foo -is [System.Object[]] # True + ``` +- `default` block is not required(`$null` will be returned when no case is matched) +- can match for not only a singular object but an collection + ```ps1 + $foo = switch (1, 2, 3) { } + ``` +- use `continue` to skip current enumeration + ```ps1 + switch (1, 2) { + 1 { continue } # I don't want to preceed with this value 1, next! + 2 { "aha" } + } # aha + ``` + +There's three options available `switch`(specifically for `string` macthing): +- `-Exact`: the default option that matches the string by literal, can be elided +- `-Regex`: match by regex condition +- `-Wildcard`: match by wildcard condition +- `-CaseSensetive`: case-sensitive matching, can be combined with any of other three options + ### Constant Pattern +Constant pattern is specifically for numbers and strings. + +While `switch` has dedicated options for strings but those does not apply on other literals. +However, when a non-string type is tried to match the string case by no matter which option you specified, it will be evaluated to string. + +```ps1 +$foo = 1 +$bar = switch -Exact ($foo) { + 1 { "one" } + 2 { "two" } + 3 { "three" } + 1 { "one" } # reachable # [!code warning] + '1' { "stringified one" } # matched too! # [!code highlight] +} + +$bar = switch ($foo) { # -Exact can be elided # [!code highlight] + 1 { "one"; break } + 2 { "two" } + 3 { "three" } + 1 { "one" } # not reachable # [!code highlight] + default { "ok I am the last resort" } +} +``` + ### Type Pattern -### Regex Pattern +Nothing else + +```ps1 +switch ("foo") { + { $_ -is [string] -and $_.Length -gt 0 } { 'all right' } +} +``` + +### Regex & Wildcard Pattern + +I don't have much to say + +```ps1 +switch -Regex -CaseSensetive ("hello") { + "h\d+" { "..." } + "H\w+" { "..." } +} + +``` + +## Trap -### Wildcard Pattern +`trap` is been called as a statement in PowerShell worlatchedd, but this is more like a `trap` block, for it: +- serve as a isolated process for handling any error raised in the script or function +- can be defined anywhere inside the script or function +But what makes it different from *block* is, you can specify multiple `trap` for different error types. +**And PowerShell only run the most specific `trap` statement for the error** +> [!NOTE] +> Use `$_` to access the captured error object inside `trap` + +> [!WARNING] +> Do not defined more than one `trap` for a same error type, only the first would be executed + +```ps1 +param() + +trap { + "Any error was triggered" +} + +trap [System.StackOverflowException] { + "A dedicated exception happened" +} +``` + +`trap` does not break the process, but only executes when particular error happens unless, you use `break`. + +```ps1 +param() + +trap { + "Stop here" + break +} + +ErrorHere + +Write-Host "Not reachable here" # [!code warning] +``` + +> [!NOTE] +> `continue` is also available in `trap`, the only difference is it does not write the error to error stream diff --git a/docs/document/PowerShell/docs/Standard IO/Stream Redirection.md b/docs/document/PowerShell/docs/Standard IO/Stream Redirection.md new file mode 100644 index 00000000..4d40f7ef --- /dev/null +++ b/docs/document/PowerShell/docs/Standard IO/Stream Redirection.md @@ -0,0 +1,42 @@ +# Stream Redirection + +The streams are implicitly working everyday we use redirection operator `>`, `>>` in PowerShell. +Streams are `Success`, `Error`, `Warning` ... that's exactly the counterpart of `Write-Output`, `Write-Error` ... + +> [!NOTE] +> See: [Output Streams](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-7.4#redirectable-output-streams) + +> [!NOTE] +> Append redirection `>>` is only available for files + +## Redirect to File + +When you write to a file using `>` to redirect content, it's actually redirecting the `Success` stream to the file. + +```ps1 +gci > foo.txt +# equivalent to +gci 1> foo.txt # 1 represents the Success stream +``` + +## Redirect to Another Stream + +```ps1 +gci 1>&2 # redirect Success stream to Error stream +``` + +## Redirect at One Go + +You can apply multiple redirection for a same source. + +```ps1 +& { Write-Warning "hello"; Write-Error "hello"; Write-Output "hi" } 3>&1 2>&1 > C:\Temp\redirection.log +``` + +## Suppress Message from Streams + +If you only care specific message from streams or exculde particular stream, redirect it to `$null` + +```ps1 +ffmpeg -h *> $null # swollow all streams output from ffmpeg +``` diff --git a/docs/document/PowerShell/docs/Terminology.md b/docs/document/PowerShell/docs/Terminology.md index 700ddf5d..b67af94d 100644 --- a/docs/document/PowerShell/docs/Terminology.md +++ b/docs/document/PowerShell/docs/Terminology.md @@ -23,3 +23,13 @@ By this approach, you can expose minimal privileges and custom utilities to user Each Runspace creates isolated session state just like a normal powershell instance. A normal powershell can be referred as a Runspace too. + +## Execution Policy + +Execution Policy is dedicated for Windows platform, it restricts the authority to execute a valid PowerShell script or command. + +- `AllSigned`: requires scripts to be signed by trusted-publisher +- `Bypass`: does not block anything +- `Default`: `Restricted` for Windows personal and `RemoteSigned` for Windows Server +- `Unrestricted`: default and unchangeable for non-windows platform +- `Restricted`: no script allowed; command execution allowed