如何更改文件列表的读取属性?
我是 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
简短回答:
下面是长回答
嗯,有些事情是错误的。
$file
实际上是一个string[]
,包含文件的行。因此,IsReadOnly
属性适用于string[]
,而不适用于这些字符串所表示的实际文件,而这些字符串恰好是文件名。因此,如果我理解正确的话,您正在尝试读取一个包含其他文件名的文件,每一行一个文件名。并清除这些文件的只读属性。
从
Get-Content
开始在这里并没有错。我们肯定会需要它:现在我们有一个文件名列表。要访问文件的属性,我们需要将这些文件名转换为实际的 FileInfo 对象并对其进行操作。或者我们将文件名传递给
Set-ItemProperty
的-Path
参数。我将首先采用第一种方法,然后再采用另一种方法。因此,我们有一堆文件名,并且需要其中的
FileInfo
对象。这可以通过 foreach 循环来完成(因为我们需要对列表中的每个文件执行此操作):然后您可以循环文件名并设置 IsReadOnly 属性对他们每个人来说:
这是又长又麻烦的变体。但这可能最适合没有 PowerShell 经验的人。通过使用管道,您可以减少对多个事物集合的需求。管道将对象从一个 cmdlet 传输到另一个 cmdlet,并且这些对象仍然具有类型。
因此,通过写作,
我们获得了完全相同的结果。我们读取文件的内容,得到一堆
string
。这些被传递给 Get-Item,它恰好知道如何处理管道输入:它将这些对象视为文件路径;这正是我们所需要的。然后,Get-Item
将FileInfo
对象进一步发送到管道,此时我们循环遍历它们并将只读属性设置为false
。现在,时间更短了,而且经过一点练习,也许会更容易。但距离理想还很远。正如我之前所说,我们可以使用 Set-ItemProperty 来设置文件的只读属性。我们可以利用
Set-ItemProperty
可以将字符串数组作为其-Path
参数的输入。我们在这里使用临时变量,因为
Set-ItemProperty
不会直接接受传入字符串作为-Path
的值。但我们可以内联这个临时变量:需要使用
Get-Content
调用周围的括号来告诉 PowerShell 这是一个单一参数,应该首先对其进行求值。,我们可以利用每个参数都在 Set-ItemProperty 期望的位置使用这一事实,因此我们可以省略参数名称并仅使用值:
然后 然后我们可以将 cmdlet 名称缩短为其默认别名:
我们实际上可以将
$false
写为0
以节省更多空间,因为0
是用作布尔值时转换为$false
。但我认为这里缩短就足够了。Short answer:
Long answer below
Well, some things are wrong with this.
$file
is actually astring[]
, containing the lines of your file. So theIsReadOnly
property applies to thestring[]
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: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 ofSet-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 aforeach
loop (since we need to do this for every file in the list):You can then loop over the file names and set the
IsReadOnly
property on each of them: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
we're achieving exactly the same result. We read the contents of the file, getting a bunch of
string
s. Those are passed toGet-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 sendsFileInfo
objects further down the pipeline, at which point we are looping over them and setting the read-only property tofalse
.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 thatSet-ItemProperty
can take an array of strings as input for its-Path
parameter.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: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:And then we can shorten the cmdlet names to their default aliases:
We could actually write
$false
as0
to save even more space, since0
is converted to$false
when used as a boolean value. But I think it suffices with shortening here.约翰内斯(Johannes)对您遇到的问题背后的理论有独家报道。我只是想指出,如果您碰巧使用 PowerShell 社区扩展,您可以使用可感知管道的 Set-Writable 和 Set-ReadOnly 命令,例如:
或简短的别名形式:
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.:
or the short, aliased form:
The alias for Set-ReadOnly is sro. I use these commands weekly if not daily.