将Powershell命令的详细程度降低到最小形式

将Powershell命令的详细程度降低到最小形式,powershell,Powershell,我正在我的一个Powershell脚本中执行以下操作: newitem-ItemType目录路径“MyFolder” 输出如下所示: function New-Folder { [CmdletBinding()] Param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Path ) New-Item $Path -Type Directory | Select-Ob

我正在我的一个Powershell脚本中执行以下操作:

newitem-ItemType目录路径“MyFolder”
输出如下所示:

function New-Folder {
  [CmdletBinding()]
  Param(
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]$Path
  )

  New-Item $Path -Type Directory | Select-Object -Expand FullName
}
PS C:\>。\example.ps1
目录:C:\
模式LastWriteTime长度名称
----                -------------     ------ ----
d---2015年7月12日晚上9:52我的文件夹
 
PS C:\>
总共有八行输出,真是惊人。我的脚本作为msbuild文件中任务的一部分运行,而VisualStudio中的输出空间有限,因此这相当麻烦

现在我知道我可以通过管道将输出传输到
Out Null
来抑制所有这些行,但是我确实喜欢一些关于命令执行情况的反馈。一条反馈线是最佳的

我想这种解决办法可以奏效:

写入主机“创建文件夹MyFolder”
新项目-项目类型目录-路径“MyFolder”|输出空值
但是一直记住/写这些是很乏味的

我想另一个解决方法是创建某种包装器功能,但由于
newitem
只是一个示例,因此我必须编写许多包装器。相反,我正在寻找一种跨
***-Item
cmdlet工作的技术

有没有什么方法可以降低像
newitem
这样的命令的冗长程度,而不必求助于变通方法

我查过了,但没有发现任何线索。也许我的变通方法是实现这一目标的唯一途径

底线:是否有一种惯用方法将新项目输出压缩到一行?

为什么不简单地:

New-Item -ItemType Directory -Path "MyMyFolder" | % { Write-Output "Directory created !" }

如果您正在编写脚本,我建议使用try-catch。这样你就可以确定它是否有效。这是一个多一点的编码,但绝对值得做的,如果有一个脚本不按预期运行的可能性

try {
  New-Item -ItemType Directory -Path "MyFolder" -ErrorAction Stop | Out-Null
  Write-Output "Created folder MyFolder"
}
catch {
  "Failed to create folder MyFolder"
}

New Item
的管道输出是一个
System.IO.DirectoryInfo
对象,向控制台发送
DirectoryInfo
的默认处理是您看到的详细输出

PS> cd d:\temp
PS> $output = New-Item -ItemType Directory -Path "MyFolder"
PS> $output

    Directory: D:\temp

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2015-12-07     13:15            foo
(这里的
$output
变量是多余的;我只是在示例中使用它来缩短行,避免在测试时创建一堆新目录。:)

减少冗长的一种方法是使用管道过滤器仅输出您感兴趣的数据,而不是整个
DirectoryInfo
。将其格式化为字符串时,输出仅占用一行。通常这是属性
Name
FullName

PS> $output | Select-Object -ExpandProperty FullName
D:\temp\MyFolder
创建日志文件时,了解操作内容也很有用。您可以使用
foreach
从DirectoryInfo对象创建自定义字符串

PS> $output | % { "Created directory '$($_.Name)' in parent '$($_.Parent.FullName)'" }
Created directory 'MyFolder' in parent 'D:\Temp'
而且,如果您打算经常这样做,您甚至可以为它创建一个速记过滤器函数

PS> filter Format-DirectoryOperation($verb) {
>>    "$verb directory '$($_.Name)' in parent '$($_.Parent.FullName)'"
>>  }
PS> $output | Format-DirectoryOperation('Created')
Created directory 'foo' in parent 'D:\temp'

惯用的方法是展开所创建对象的
Name
(或
FullName
)属性:

New-Item 'foo' -Type Directory | select -Expand FullName
如果您经常需要此功能,可以将其包装在如下自定义函数中:

function New-Folder {
  [CmdletBinding()]
  Param(
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]$Path
  )

  New-Item $Path -Type Directory | Select-Object -Expand FullName
}

并将其输入到您的中。

以下是一些用于更改PS cmdlet输出的其他技术。一种是通过
format.ps1xml
文件(
help about_format.ps1xml
)。PS1XML文件实际上并不直接以cmdlet的输出为目标,而是以各种格式方法的输出为目标。format-*cmdlet对应于各种格式方法。format-*cmdlet(显式或隐式)用于显示选定.NET类型的实例。因此,通过修改或创建.PS1XML文件,您可以有效地更改由*项cmdlet生成的对象实例的显示方式

另一种技术是包装或代理cmdlet。下面是描述这一点的例子


编写自己的“PS提供者”的另一种可能性(尝试
获取psprovider
以查看现有提供者)。*-项cmdlet专门设计用于与内置和附加提供程序一起使用。通过编写文件系统提供程序,可以对*-项cmdlet施加很大的控制。您需要提出另一个驱动器号约定,而不是C:,D:,等等,因为已经使用了该约定。但希望您的MSBUILD文件没有太多硬编码驱动器号使用。

我很惊讶没有看到像这样简单的东西

$output = New-Item -ItemType Directory -Path "MyFolder"
"$output"

d:\test\MyFolder
将DirectoryInfo强制转换为字符串将其转换为单行名称,并将其嵌入到字符串中的命令中:

->

命令行键入时可以用别名缩短->

"$(ni -i d MyFolder)"
->


但是,正如所评论的,“相反,我正在寻找一种可以跨__-Item cmdlet工作的技术。”这种情况不太可能发生,因为问题不在于cmdlet是否冗长,而在于cmdlet的返回值,而这取决于您使用的PSProvider。在本例中,它返回一个DirectoryInfo,但如果您执行了
cd变量:\$r=New Item-ItemType directory-Value test-Name test
返回是一个PSVariable类型,等等其他东西。

您是否研究过将输出管道化到一个
格式-*
cmdlet中?@RyanBemrose-Hmm,不,没有想到这一点。你推荐哪一个?唯一适用的是
格式自定义
,并且(如果/当我可以让它工作时)与@sodawillow的答案类似,对吗?我的答案不是很正统,但它允许您输出我所要求的消息,因为
格式-*
是控制输出的惯用方法,但我不知道你要怎么做。我认为您最好的选择是使用@sodawillow的技术(在我的回答中进行了扩展)将管道上的输出对象从
DirectoryInfo
转换为
String
,这将更加简洁地显示。您关心的所有输出都在XML文件中定义。如果您确实不喜欢DirectoryInfo对象的标准输出,您可以更改
"$(md MyFolder)"