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 string
s. 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.