Skip to content

Commit 0428e83

Browse files
committed
main
1 parent 9622452 commit 0428e83

File tree

6 files changed

+270
-53
lines changed

6 files changed

+270
-53
lines changed

docs/document/PowerShell/docs/File System/4.Manipulate Item.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
# Manipulate Item
2+
23
## Create Item
34

45
Powershell uses a single cmdlet named `New-Item` to represent all kinds of creation logic for file system items like folder, file, symlinks...
56

67
> [!TIP]
78
> Use `ni` alias for `New-Item`.
89
9-
## File
10+
### File
1011

1112
`New-Item` creates file without extra options by default.
1213

@@ -25,7 +26,7 @@ New-Item <file_path>
2526
> [!TIP]
2627
> Use `-Force` flag to overwrite existing target.
2728
28-
### Directory
29+
#### Directory
2930

3031
```ps1
3132
New-Item <dir_path> -ItemType Directory
@@ -42,7 +43,7 @@ mkdir <dir_path>
4243
> [!TIP]
4344
> Use `-Force` flag to overwrite existing target.
4445
45-
### Symbolic Link
46+
#### Symbolic Link
4647

4748
```ps1
4849
New-Item <symlink_path> -Target <source> -ItemType SymbolicLink
@@ -54,26 +55,25 @@ New-Item <symlink_path> -Target <source> -ItemType SymbolicLink
5455
> [!TIP]
5556
> Use `-Force` flag to overwrite existing target.
5657
57-
### Ignore Wildcards
58-
59-
`-Path` translates wildcards by default, if you do need to include special characters from wildcards syntax for your new item, use `-LiteralPath`.
60-
61-
```ps1
62-
New-Item -LiteralPath 'foo*.txt' # creates a file literally named `foo*.txt`
63-
```
64-
6558
## Delete
6659

6760
- delete file
6861

6962
```ps1
7063
ri <file>
64+
gci -file | ri
7165
```
7266

7367
- delete folder
7468

7569
```ps1
7670
ri -rec -force <folder>
71+
gci -dir | ri -rec -force
7772
```
7873

79-
### Rename
74+
## Rename
75+
76+
```ps1
77+
rni <item> -NewName { $_.Name -replace 'foo', 'bar' }
78+
gci -file | rni -NewName { $_.Name -replace 'foo', 'bar' }
79+
```

docs/document/PowerShell/docs/History.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
- Session history
66

77
```ps1
8-
h | Select-String <text>
8+
h | sls <text>
99
```
1010

1111
- All history
1212

1313
```ps1
14-
gc (Get-PSReadLineOption).HistorySavePath | Select-String <text>
14+
gc (Get-PSReadLineOption).HistorySavePath | sls <text>
1515
```

docs/document/PowerShell/docs/Job/Job Manipulation.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,16 @@ The return type of job result is not certain. It depends on the action you speci
8282
- `-Timeout`: wait until timeout were reached
8383
- `-Force`: wait for `Suspended` and `Disconnected`
8484
85+
### `Wait-Job` or `Receive-Job -Wait`
86+
87+
You may be confused about `Wait-Job` and `Receive-Job -Wait`; They both wait for jobs, but `Wait-Job` respects the order of how jobs were created while `Receive-Job` only collects by order of completion time.
88+
89+
`Wait-Job` waits for all child jobs to complete without collecting anything, so the order remains, finally `Receive-Job` retrieve the result by that order.
90+
Direct `Receive-Job` collects immediately when each job is completed, so the order is random.
91+
92+
```ps1
93+
# this is always sorted
94+
1..10 | foreach -Parallel { echo $_ } -AsJob | wjb | rcjb # 1 2 3 4 5 .. 10
95+
# this has random order
96+
1..10 | foreach -Parallel { echo $_ } -AsJob | rcjb -Wait
97+
```

docs/document/PowerShell/docs/Job/Thread Job.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,8 @@ $job.GetType().Name # ThreadJob
3030
```ps1
3131
1..10 | foreach -Parallel { echo $_ } -AsJob | rcjb -Wait
3232
```
33+
34+
## Thread Safety
35+
36+
Do not mutate or access member of a shared variable in thread jobs unless you use thread-safe types!
37+

docs/document/PowerShell/docs/Language/Function.md

Lines changed: 163 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,5 @@
11
# Function
22

3-
## Return
4-
5-
Powershell allows implicit return, and multiple implicit returns.
6-
7-
> [!NOTE]
8-
> Implicit returns are auto-collected as an array or single value.
9-
> And it does not print out anything.
10-
11-
```ps1
12-
[int] function Sum {
13-
param([int]$l, [int]$r)
14-
$l + $r # implicit return # [!code highlight]
15-
}
16-
17-
# You won't need to declare an array and append it on each loop!
18-
# they're collected automatically as they're implicit returns
19-
function Foo {
20-
for($i = 0; $i -lt 10; $i = $i + 1) {
21-
$i
22-
}
23-
}
24-
25-
(Foo).GetType().Name # object[] # [!code highlight]
26-
```
27-
28-
Explicit return is surely supported, but more like a necessity to exit inside a flow.
29-
30-
```ps1
31-
[int] function Sum {
32-
param([int]$l, [int]$r)
33-
return $l + $r # explicit return # [!code highlight]
34-
$r + $l # not reachable # [!code warning]
35-
}
36-
```
373

384
## Parameter
395

@@ -199,11 +165,38 @@ Will throw an error if any parameter does not satisfies the condition.
199165
param (
200166
[ValidateScript({ ($_ % 2) -ne 0 })]
201167
[int[]]$Odd
202-
[ValidateScript({ $_.Length < 5 })]
168+
[ValidateScript({ $_.Length < 5 }, ErrorMessage = "{0} is not valid")] # 0 is the input value
203169
[string]$Name
204170
)
205171
```
206172

173+
- `ValidateLength(min, max)`
174+
- `ValidateCount(min, max)`
175+
- `AllowNull()`
176+
- `AllowEmptyString()`
177+
- `AllowEmptyCollection()`
178+
- `ValidatePattern(regex)`
179+
- `ValidateRange(min, max)`
180+
- or any value of enum `ValidateRangeKind`: `Positive`, `Negative`, `NonNegative`, `NonPositive`
181+
```ps1
182+
param(
183+
[ValidateRange("Positive")]
184+
[int]$Number
185+
)
186+
```
187+
- `ValidateSet(foo, bar, ...)`: provides completion for predefined entries
188+
- `ValidateNotNull()`
189+
- `ValidateNotNullOr()`
190+
- `ValidateNotNullOrEmpty()`: not a empty string or collection or null
191+
- `ValidateNotNullOrWhiteSpace()`
192+
- `ValidateDrive(drive, ...)`: check whether specified path is valid from certain PSDrive
193+
```ps1
194+
param(
195+
[ValidateDrive("C", "D")]
196+
[string]$Path
197+
)
198+
```
199+
207200
### Pass By Reference
208201
209202
Parameter passed by reference is implemented by a wrapper `System.Management.Automation.PSReference`.
@@ -279,6 +272,139 @@ function Foo {
279272
}
280273
```
281274
282-
## Lifetime
275+
## Mimicking Cmdlet
276+
277+
A function would generally not acting a cmdlet unless it was annotated with `CmdletBinding()` attribute.
278+
279+
`CmdletBinding()` can have the following properties:
280+
281+
- `DefaultParameterSetName`: name of implicit Parameter Set
282+
- `HelpURI`: link to documenetation
283+
- `SupportsPaging`: implicitly adds parameters `-First`, `-Skip`, `-IncludeTotalCount`, value accessible by `$PSCmdlet.PagingParameters`
284+
```ps1
285+
function foo {
286+
[CmdletBinding(SupportsPaging)]
287+
param()
288+
$PSCmdlet.PagingParameters.Skip
289+
$PSCmdlet.PagingParameters.First
290+
$PSCmdlet.PagingParameters.IncludeTotalCount
291+
}
292+
```
293+
- `SupportsShouldProcess`: implicitly adds `-Confirm` and `-WhatIf`
294+
- `ConfirmImpact`: specify impact of `-Confirm`
295+
- `PositionalBinding`:
296+
297+
<!-- TODO: complete description for ConfirmImpact and PositionalBinding -->
298+
299+
## Parameter Set
300+
301+
How a same cmdlet manage different syntax for different usages? The trick is **Parameter Set**.
302+
Parameter Set is a classification on paramater to distinguish or limit the use of parameters from scenarios.
303+
304+
- a parameter set must have at least one unique parameter to others to identify the set
305+
- a parameter can have multiple Parameter Set
306+
- a parameter can have different roles in different Parameter Set, can be mandatory in one and optional in another
307+
- a parameter without explicit Parameter Set belongs to all other Parameter Set
308+
- at least one parameter in the Parameter Set is mandatory
309+
- only one parameter in set can accept `ValueFromPipeline`
310+
311+
### Parameter Set Idetifier at Runtime
312+
313+
`$PSCmdlet.ParameterSetName` reflects the Parameter Set been chosen when a cmdlet is executing with certain syntax.
314+
315+
316+
## Common Parameters
317+
318+
Any function or cmdlet applied with `CmdletBinding()` or `Parameter()` attribute has the following implicit parameters added by PowerShell:
319+
320+
- ErrorAction (ea): specify action on error
321+
- ErrorVariable (ev): declare **inline** and store the error on the variable instead of `$Error`. Use `-ErrorVariable +var` to append error to the variable
322+
```ps1
323+
gcm foo -ev bar # inline declaration for $bar
324+
$bar # contains error
325+
gcm baz -ev +bar
326+
$bar # contains two errors
327+
```
328+
> [!NOTE]
329+
> The inline variable is an `ArrayList`
330+
- InformationAction (infa): similar to `ea`
331+
- InformationVariable (iv): similar to `ev`
332+
- WarningAction (wa): similar to `ea`
333+
- WarningVariable (wv): similar to `ev`
334+
- ProgressAction (proga)
335+
- OutVariable (ov): declare **inline** and store the output to the variable. Similar to `ev`.
336+
It's interesting that `-OutVariable` collects incremnentally.
337+
It collects new item from pipeline on iteration.
338+
```ps1
339+
1..5 | % { $_ } -OutVariable foo | % { "I am $foo" }
340+
# I am 1
341+
# I am 1,2
342+
# I am 1,2,3
343+
# I am 1,2,3,4
344+
# I am 1,2,3,4,5
345+
```
346+
347+
- Debug (db): print verbose debug message, overrides `$DebugPreference`
348+
- OutBuffer (ob)
349+
- PipelineVariable (pv) <!-- TODO: PipelineVariable -->
350+
- Verbose (vb): whether display the verbose message from `Write-Verbose`
351+
352+
## Mitigation Parameters
353+
354+
- WhatIf (wi)
355+
- Confirm (cf)
356+
357+
## Return
358+
359+
Powershell allows implicit return, and multiple implicit returns.
360+
361+
> [!NOTE]
362+
> Implicit returns are auto-collected as an array or single value.
363+
> And it does not print out anything.
364+
365+
```ps1
366+
function Sum {
367+
param([int]$l, [int]$r)
368+
$l + $r # implicit return # [!code highlight]
369+
}
370+
371+
# You won't need to declare an array and append it on each loop!
372+
# they're collected automatically as they're implicit returns
373+
function Foo {
374+
for($i = 0; $i -lt 10; $i = $i + 1) {
375+
$i
376+
}
377+
}
378+
379+
(Foo).GetType().Name # object[] # [!code highlight]
380+
```
381+
382+
Explicit return is surely supported, but more like a necessity to exit inside a flow.
283383

284-
- Function should be define before it was called.
384+
```ps1
385+
function Sum {
386+
param([int]$l, [int]$r)
387+
return $l + $r # explicit return # [!code highlight]
388+
$r + $l # not reachable # [!code warning]
389+
}
390+
```
391+
392+
### Output Type
393+
394+
`OutputTypeAttribute(type: System.Type | System.String, parameterSet?: System.String)` matters when you need auto generated help for the function you write.
395+
A function can have different return types for different parameter sets.
396+
PowerShell never do type checking by this attribute, it's just responsible for help generation, write with carefulness!
397+
398+
```ps1
399+
[CmdletBinding(DefaultParameterSetName = 'ID')]
400+
[OutputType('System.Int32', ParameterSetName = 'ID')]
401+
[OutputType([string], ParameterSetName = 'Name')]
402+
param (
403+
[Parameter(Mandatory = $true, ParameterSetName = 'ID')]
404+
[int[]]
405+
$UserID,
406+
[Parameter(Mandatory = $true, ParameterSetName = 'Name')]
407+
[string[]]
408+
$UserName
409+
)
410+
```

0 commit comments

Comments
 (0)