3

我是powershell新手。我使用了一个示例脚本,并将第一行中的 get-item 替换为 get-content。修改后的脚本如下所示:

$file = get-content "c:\temp\test.txt"
if ($file.IsReadOnly -eq $true)
{
$file.IsReadOnly = $false
}

所以从本质上讲,我正在尝试对存储为 UNC 路径的 test.txt 中包含的项目进行操作

\\testserver\testshare\doc1.doc
\\testserver2\testshare2\doc2.doc

运行脚本时不会报告错误,即使在第一次进入时也不会执行任何操作。

4

2 回答 2

8

简短的回答:

sp (gc test.txt) IsReadOnly $false

下面长答案


好吧,有些事情是错误的。

$file实际上是 a string[],包含文件的行。因此,该IsReadOnly属性适用于string[]不是由这些字符串表示的实际文件,这些字符串恰好是文件名。

因此,如果我对您的理解正确,您正在尝试读取一个文件,其中包含其他文件名,每行一个。并清除这些文件的只读属性。

Get-Content这里开始并没有错。我们肯定会需要它:

$filenames = Get-Content test.txt

现在我们有了一个文件名列表。要访问文件的属性,我们需要将这些文件名转换为实际FileInfo对象并对其进行操作。或者我们将文件名传递-PathSet-ItemProperty.

我会先采用第一种方法,然后再采用另一种方法。所以我们有一堆文件名,并希望FileInfo从中获取对象。这可以通过foreach循环来完成(因为我们需要对列表中的每个文件执行此操作):

$files = (foreach ($name in $filenames) { Get-Item $name })

然后,您可以遍历文件名并为IsReadOnly每个文件设置属性:

foreach ($file in $files) {
    $file.IsReadOnly = $false
}

这是一个冗长而繁琐的变体。但它可能最适合没有 PowerShell 经验的人。通过使用管道,您可以减少对多个事物集合的需求。管道将对象从一个 cmdlet 传输到另一个,并且这些对象仍然具有类型。

所以通过写

Get-Content test.txt | Get-Item | ForEach-Object { $_.IsReadOnly = $false }

我们正在实现完全相同的结果。我们读取文件的内容,得到一堆strings。那些被传递给Get-Item恰好知道如何处理管道输入的对象:它将这些对象视为文件路径;正是我们在这里需要的。Get-Item然后将FileInfo对象进一步发送到管道中,此时我们循环它们并将只读属性设置为false.

现在,这更短了,稍加练习,可能会更容易。但它仍然远非理想。正如我之前所说,我们可以使用Set-ItemProperty设置文件的只读属性。我们可以利用这样一个事实,即Set-ItemProperty可以将字符串数组作为其-Path参数的输入。

$files = Get-Content test.txt
Set-ItemProperty -Path $files -Name IsReadOnly -Value $false

我们在这里使用一个临时变量,因为Set-ItemProperty不会-Path直接接受传入的字符串作为值。但是我们可以内联这个临时变量:

Set-ItemProperty -Path (Get-Content test.txt) -Name IsReadOnly -Value $false

调用周围的括号Get-Content需要告诉 PowerShell 这是一个单独的参数,应该首先进行评估。

然后我们可以利用这些参数中的每一个都在Set-ItemProperty预期的位置使用这一事实,因此我们可以省略参数名称并只保留值:

Set-ItemProperty (Get-Content test.txt) IsReadOnly $false

然后我们可以将 cmdlet 名称缩短为其默认别名:

sp (gc test.txt) IsReadOnly $false

我们实际上可以写$falseas0来节省更多空间,因为当用作布尔值时0会转换为。$false但我认为在这里缩短就足够了。

于 2009-10-04T13:38:12.297 回答
2

约翰内斯对您遇到的问题背后的理论有独到见解。我只是想指出,如果您碰巧使用PowerShell 社区扩展,您可以通过使用管道感知的 Set-Writable 和 Set-ReadOnly 命令来执行此操作,例如:

Get-Content "c:\temp\test.txt" | Set-Writable

或简短的别名形式:

gc "c:\temp\test.txt" | swr

Set-ReadOnly 的别名是 sro。如果不是每天,我每周都会使用这些命令。

于 2009-10-04T18:41:50.190 回答