New-Item 更改函数 return 值
New-Item changes function return value
我想编写一个函数,在指定文件夹内创建一个具有指定名称的文件夹(如果它不存在)。
事实证明,根据调用 New-Item
函数 return 不同的值。而且我无法弄清楚它实际上与 New-Item
有什么关系。
$folderPath = "C:\tmp"
function CreateFolder([string] $name, [string] $parentFolder)
{
$path = "$parentFolder$name"
if(!(Test-Path $path))
{
New-Item -path $parentFolder -name $name -itemtype Directory
}
return $path
}
$FOLDER_NAME = "folder1"
$destination = CreateFolder $FOLDER_NAME $folderPath
echo $destination.GetType()
如果 folder1 不存在 它将 return:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
否则:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
这不是问题,除非 Move-Item
支持 Object[]
作为 -destination
参数。
echo $destination
returns:
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\tmp\folder1
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\tmp
PSChildName : folder1
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : True
Name : folder1
Parent : tmp
Exists : True
Root : C:\
FullName : C:\tmp\folder1
Extension :
CreationTime : 13.08.2015 10:53:11
CreationTimeUtc : 13.08.2015 7:53:11
LastAccessTime : 13.08.2015 10:53:11
LastAccessTimeUtc : 13.08.2015 7:53:11
LastWriteTime : 13.08.2015 10:53:11
LastWriteTimeUtc : 13.08.2015 7:53:11
Attributes : Directory, NotContentIndexed
BaseName : folder1
Target :
LinkType :
Mode : d-----
我找到的唯一解决方案是不使用函数:
$folderPath = "C:\tmp"
$FOLDER_NAME = "folder1"
$destination = "$folderPath$FOLDER_NAME"
if(!(Test-Path $destination))
{
New-Item -path $folderPath -name $FOLDER_NAME -itemtype Directory
}
Move-Item -path "C:\tmp\file1" -destination $destination
如果 folder1 不存在:
Каталог: C:\tmp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 13.08.2015 11:06 folder1
MemberType : TypeInfo
DeclaringType :
DeclaringMethod :
ReflectedType :
StructLayoutAttribute : System.Runtime.InteropServices.StructLayoutAttribute
GUID : 296afbff-1b0b-3ff5-9d6c-4e7e599f8b57
Module : CommonLanguageRuntimeLibrary
Assembly : mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
TypeHandle : System.RuntimeTypeHandle
FullName : System.String
Namespace : System
AssemblyQualifiedName : System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
BaseType : System.Object
TypeInitializer :
IsNested : False
Attributes : AutoLayout, AnsiClass, Class, Public, Sealed, Serializable, BeforeFieldInit
GenericParameterAttributes :
IsVisible : True
IsNotPublic : False
IsPublic : True
IsNestedPublic : False
IsNestedPrivate : False
IsNestedFamily : False
IsNestedAssembly : False
IsNestedFamANDAssem : False
IsNestedFamORAssem : False
IsAutoLayout : True
IsLayoutSequential : False
IsExplicitLayout : False
IsClass : True
IsInterface : False
IsValueType : False
IsAbstract : False
IsSealed : True
IsEnum : False
IsSpecialName : False
IsImport : False
IsSerializable : True
IsAnsiClass : True
IsUnicodeClass : False
IsAutoClass : False
IsArray : False
IsGenericType : False
IsGenericTypeDefinition : False
IsConstructedGenericType : False
IsGenericParameter : False
GenericParameterPosition :
ContainsGenericParameters : False
IsByRef : False
IsPointer : False
IsPrimitive : False
IsCOMObject : False
HasElementType : False
IsContextful : False
IsMarshalByRef : False
GenericTypeArguments : {}
IsSecurityCritical : False
IsSecuritySafeCritical : False
IsSecurityTransparent : True
UnderlyingSystemType : System.String
Name : String
CustomAttributes : {[System.SerializableAttribute()], [System.Reflection.DefaultMemberAttribute("Chars")], [System.Runtime.InteropServices.ComVisibleAttribute(
(Boolean)True)], [__DynamicallyInvokableAttribute()]}
MetadataToken : 33554536
否则:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
工作示例 根据 Ansgar 的建议:
$folderPath = "C:\tmp"
function GetDestination {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$Name,
[Parameter(Mandatory=$true)]
[string]$ParentFolder
)
$path = Join-Path $ParentFolder $Name
if(Test-Path -LiteralPath $path) {
Get-Item -LiteralPath $path
} else {
New-Item -Path $ParentFolder -Name $Name -ItemType Directory
}
}
$FOLDER_NAME = "folder1"
$destination = GetDestination $FOLDER_NAME $folderPath
Move-Item -LiteralPath "C:\tmp\file1" -Destination $destination
New-Item
returns 创建的对象,PowerShell 函数 return 所有未捕获的输出,而不仅仅是 return
关键字的参数。
In Windows PowerShell, the results of each statement are returned as output, even without a statement that contains the Return keyword. Languages like C or C# return only the value or values that are specified by the Return keyword.
这意味着如果路径已经存在,您的函数 return 只是路径字符串。否则,它 return 是一个包含新 DirectoryInfo
对象 和 路径字符串的数组。
根据你想要的是字符串还是 DirectoryInfo
对象 returned 你可以抑制 New-Item
:
的输出
if (!(Test-Path $path)) {
New-Item -Path $parentFolder -Name $name -ItemType Directory | Out-Null
}
return $path
或删除 return
语句,而是在路径上调用 Get-Item
的地方添加一个 else
分支:
if (!(Test-Path $path)) {
New-Item -Path $parentFolder -Name $name -ItemType Directory
} else {
Get-Item $path
}
更笼统地说,我建议对您的代码进行一些修改:
- 将
-LiteralPath
参数与 Test-Path
一起使用,这样当路径包含方括号等特殊字符时,您就不会 运行 遇到问题。
- 使用
Join-Path
构建路径,因为它会自动处理路径分隔符。
- 使用 advanced parameter definitions,这将使您能够强制参数化、定义参数顺序、验证输入以及许多其他事情。
- 使用 approved verbs 的 PowerShell 命名约定作为您的函数名称。
示例:
function New-Folder {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$Name,
[Parameter(Mandatory=$true)]
[string]$ParentFolder
)
$path = Join-Path $ParentFolder $Name
if (-not (Test-Path -LiteralPath $path)) {
New-Item -Path $ParentFolder -Name $Name -ItemType Directory
} else {
Get-Item -LiteralPath $path
}
}
在这种情况下,我决定将变量 "junk" 设置为 New-Item 的 return 值:
# CRAZY HACK: Need to set the return to something or else this
# function will return the New-Item object too.
if(!(Test-Path $path))
{
$junk = New-Item -path $parentFolder -name $name -itemtype Directory
}
更好的解决方案:将输出通过管道传输到 Out-Null:
if (!(Test-Path $path))
{
New-Item -path $parentFolder -name $name -itemtype Directory | Out-Null
}
我想编写一个函数,在指定文件夹内创建一个具有指定名称的文件夹(如果它不存在)。
事实证明,根据调用 New-Item
函数 return 不同的值。而且我无法弄清楚它实际上与 New-Item
有什么关系。
$folderPath = "C:\tmp"
function CreateFolder([string] $name, [string] $parentFolder)
{
$path = "$parentFolder$name"
if(!(Test-Path $path))
{
New-Item -path $parentFolder -name $name -itemtype Directory
}
return $path
}
$FOLDER_NAME = "folder1"
$destination = CreateFolder $FOLDER_NAME $folderPath
echo $destination.GetType()
如果 folder1 不存在 它将 return:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
否则:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
这不是问题,除非 Move-Item
支持 Object[]
作为 -destination
参数。
echo $destination
returns:
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\tmp\folder1
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\tmp
PSChildName : folder1
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : True
Name : folder1
Parent : tmp
Exists : True
Root : C:\
FullName : C:\tmp\folder1
Extension :
CreationTime : 13.08.2015 10:53:11
CreationTimeUtc : 13.08.2015 7:53:11
LastAccessTime : 13.08.2015 10:53:11
LastAccessTimeUtc : 13.08.2015 7:53:11
LastWriteTime : 13.08.2015 10:53:11
LastWriteTimeUtc : 13.08.2015 7:53:11
Attributes : Directory, NotContentIndexed
BaseName : folder1
Target :
LinkType :
Mode : d-----
我找到的唯一解决方案是不使用函数:
$folderPath = "C:\tmp"
$FOLDER_NAME = "folder1"
$destination = "$folderPath$FOLDER_NAME"
if(!(Test-Path $destination))
{
New-Item -path $folderPath -name $FOLDER_NAME -itemtype Directory
}
Move-Item -path "C:\tmp\file1" -destination $destination
如果 folder1 不存在:
Каталог: C:\tmp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 13.08.2015 11:06 folder1
MemberType : TypeInfo
DeclaringType :
DeclaringMethod :
ReflectedType :
StructLayoutAttribute : System.Runtime.InteropServices.StructLayoutAttribute
GUID : 296afbff-1b0b-3ff5-9d6c-4e7e599f8b57
Module : CommonLanguageRuntimeLibrary
Assembly : mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
TypeHandle : System.RuntimeTypeHandle
FullName : System.String
Namespace : System
AssemblyQualifiedName : System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
BaseType : System.Object
TypeInitializer :
IsNested : False
Attributes : AutoLayout, AnsiClass, Class, Public, Sealed, Serializable, BeforeFieldInit
GenericParameterAttributes :
IsVisible : True
IsNotPublic : False
IsPublic : True
IsNestedPublic : False
IsNestedPrivate : False
IsNestedFamily : False
IsNestedAssembly : False
IsNestedFamANDAssem : False
IsNestedFamORAssem : False
IsAutoLayout : True
IsLayoutSequential : False
IsExplicitLayout : False
IsClass : True
IsInterface : False
IsValueType : False
IsAbstract : False
IsSealed : True
IsEnum : False
IsSpecialName : False
IsImport : False
IsSerializable : True
IsAnsiClass : True
IsUnicodeClass : False
IsAutoClass : False
IsArray : False
IsGenericType : False
IsGenericTypeDefinition : False
IsConstructedGenericType : False
IsGenericParameter : False
GenericParameterPosition :
ContainsGenericParameters : False
IsByRef : False
IsPointer : False
IsPrimitive : False
IsCOMObject : False
HasElementType : False
IsContextful : False
IsMarshalByRef : False
GenericTypeArguments : {}
IsSecurityCritical : False
IsSecuritySafeCritical : False
IsSecurityTransparent : True
UnderlyingSystemType : System.String
Name : String
CustomAttributes : {[System.SerializableAttribute()], [System.Reflection.DefaultMemberAttribute("Chars")], [System.Runtime.InteropServices.ComVisibleAttribute(
(Boolean)True)], [__DynamicallyInvokableAttribute()]}
MetadataToken : 33554536
否则:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
工作示例 根据 Ansgar 的建议:
$folderPath = "C:\tmp"
function GetDestination {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$Name,
[Parameter(Mandatory=$true)]
[string]$ParentFolder
)
$path = Join-Path $ParentFolder $Name
if(Test-Path -LiteralPath $path) {
Get-Item -LiteralPath $path
} else {
New-Item -Path $ParentFolder -Name $Name -ItemType Directory
}
}
$FOLDER_NAME = "folder1"
$destination = GetDestination $FOLDER_NAME $folderPath
Move-Item -LiteralPath "C:\tmp\file1" -Destination $destination
New-Item
returns 创建的对象,PowerShell 函数 return 所有未捕获的输出,而不仅仅是 return
关键字的参数。
In Windows PowerShell, the results of each statement are returned as output, even without a statement that contains the Return keyword. Languages like C or C# return only the value or values that are specified by the Return keyword.
这意味着如果路径已经存在,您的函数 return 只是路径字符串。否则,它 return 是一个包含新 DirectoryInfo
对象 和 路径字符串的数组。
根据你想要的是字符串还是 DirectoryInfo
对象 returned 你可以抑制 New-Item
:
if (!(Test-Path $path)) {
New-Item -Path $parentFolder -Name $name -ItemType Directory | Out-Null
}
return $path
或删除 return
语句,而是在路径上调用 Get-Item
的地方添加一个 else
分支:
if (!(Test-Path $path)) {
New-Item -Path $parentFolder -Name $name -ItemType Directory
} else {
Get-Item $path
}
更笼统地说,我建议对您的代码进行一些修改:
- 将
-LiteralPath
参数与Test-Path
一起使用,这样当路径包含方括号等特殊字符时,您就不会 运行 遇到问题。 - 使用
Join-Path
构建路径,因为它会自动处理路径分隔符。 - 使用 advanced parameter definitions,这将使您能够强制参数化、定义参数顺序、验证输入以及许多其他事情。
- 使用 approved verbs 的 PowerShell 命名约定作为您的函数名称。
示例:
function New-Folder {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$Name,
[Parameter(Mandatory=$true)]
[string]$ParentFolder
)
$path = Join-Path $ParentFolder $Name
if (-not (Test-Path -LiteralPath $path)) {
New-Item -Path $ParentFolder -Name $Name -ItemType Directory
} else {
Get-Item -LiteralPath $path
}
}
在这种情况下,我决定将变量 "junk" 设置为 New-Item 的 return 值:
# CRAZY HACK: Need to set the return to something or else this
# function will return the New-Item object too.
if(!(Test-Path $path))
{
$junk = New-Item -path $parentFolder -name $name -itemtype Directory
}
更好的解决方案:将输出通过管道传输到 Out-Null:
if (!(Test-Path $path))
{
New-Item -path $parentFolder -name $name -itemtype Directory | Out-Null
}