如何更改文件列表的读取属性?

发布于 2024-08-06 03:38:33 字数 396 浏览 8 评论 0原文

我是 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

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

I am powershell newbie. I used a sample script and made substitute from get-item to get-content in the first line.
The modified script looks like below:

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

So in essence I am trying to action items contained in test.txt stored as UNC paths

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

When running script no errors are reported and no action is performed even on first entry.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟雨扶苏 2024-08-13 03:38:33

简短回答:

sp (gc test.txt) IsReadOnly $false

下面是长回答


嗯,有些事情是错误的。

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

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

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

$filenames = Get-Content test.txt

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

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

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

然后您可以循环文件名并设置 IsReadOnly 属性对他们每个人来说:

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

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

因此,通过写作,

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

我们获得了完全相同的结果。我们读取文件的内容,得到一堆string。这些被传递给 Get-Item,它恰好知道如何处理管道输入:它将这些对象视为文件路径;这正是我们所需要的。然后,Get-ItemFileInfo 对象进一步发送到管道,此时我们循环遍历它们并将只读属性设置为 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

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

Short answer:

sp (gc test.txt) IsReadOnly $false

Long answer below


Well, some things are wrong with this.

$file is actually a string[], containing the lines of your file. So the IsReadOnly property applies to the string[] and not to the actual files represented by those strings, which happen to be file names.

So, if I'm understanding you correctly you are trying to read a file, containing other file names, one on each line. And clear the read-only attribute on those files.

Starting with Get-Content isn't wrong here. We definitely are going to need it:

$filenames = Get-Content test.txt

Now we have a list of file names. To access the file's attributes we either need to convert those file names into actual FileInfo objects and operate on those. Or we pass the file names to a -Path argument of Set-ItemProperty.

I will take the first approach first and then get to the other one. So we have a bunch of file names and want FileInfo objects from them. This can be done with a foreach loop (since we need to do this for every file in the list):

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

You can then loop over the file names and set the IsReadOnly property on each of them:

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

This was the long and cumbersome variant. But one which probably suits people best with no prior experience to PowerShell. You can reduce the need for having multiple collections of things lying around by using the pipeline. The pipeline transports objects from one cmdlet to another and those objects still have types.

So by writing

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

we're achieving exactly the same result. We read the contents of the file, getting a bunch of strings. Those are passed to Get-Item which happens to know what to do with pipeline input: It treats those objects as file paths; exactly what we need here. Get-Item then sends FileInfo objects further down the pipeline, at which point we are looping over them and setting the read-only property to false.

Now, that was shorter and, with a little practise, maybe even easier. But it's still far from ideal. As I said before, we can use Set-ItemProperty to set the read-only property on the files. And we can take advantage of the fact that Set-ItemProperty can take an array of strings as input for its -Path parameter.

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

We are using a temporary variable here, since Set-ItemProperty won't accept incoming strings as values for -Path directly. But we can inline this temporary variable:

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

The parentheses around the Get-Content call are needed to tell PowerShell that this is a single argument and should be evaluated first.

We can then take advantage of the fact that each of those parameters is used in the position where Set-ItemProperty expects it to be, so we can leave out the parameter names and stick just to the values:

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

And then we can shorten the cmdlet names to their default aliases:

sp (gc test.txt) IsReadOnly $false

We could actually write $false as 0 to save even more space, since 0 is converted to $false when used as a boolean value. But I think it suffices with shortening here.

陈年往事 2024-08-13 03:38:33

约翰内斯(Johannes)对您遇到的问题背后的理论有独家报道。我只是想指出,如果您碰巧使用 PowerShell 社区扩展,您可以使用可感知管道的 Set-Writable 和 Set-ReadOnly 命令,例如:

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

或简短的别名形式:

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

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

Johannes has the scoop on the theory behind the problem you are running into. I just wanted to point out that if you happen to be using the PowerShell Community Extensions you can perform this by using the Set-Writable and Set-ReadOnly commands that are pipeline aware e.g.:

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

or the short, aliased form:

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

The alias for Set-ReadOnly is sro. I use these commands weekly if not daily.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文