The attributes property of a file object is a bit field presented as a number and given an easily understandable value by the System.IO.FileAttributes enumeration.
A bit-field is a means of exposing multiple settings that have two states (on or off binary states) using a single number.
A byte, an 8-bit value, can therefore hold eight possible settings. A 32-bit integer, 4 bytes long, can hold 32 different settings.
The following table, whose state is described by 4 bits, has four settings:
Name: Setting4Setting3Setting2Setting1
State: On Off On Off
Binary: 1 0 1 0
Decimal: 8 4 2 1
When settings 2 and 4 are toggled on, the value of the field is the conversion of 1010 to decimal. This value is the result of 8 -bor 4, that is, 12.
A number of the possible attributes are shown in the following table:
Name |
Compressed |
Archive |
System |
Hidden |
Read-only |
Bit value |
2048 |
32 |
4 |
2 |
1 |
When a file is hidden and read-only, the value of the attributes property is 3 (2 + 1). The value 3 can be cast the FileAttributes type that shows the names of the individual flags:
PS> [System.IO.FileAttributes]3
ReadOnly, Hidden
While the value is numeric, the use of the enumeration means words can be used to describe each property:
PS> [System.IO.FileAttributes]'ReadOnly, Hidden' -eq 3
True
This opens up a number of possible ways to set attributes on a file.
The attributes may be replaced entirely:
(Get-Item 'somefile.txt').Attributes = 'ReadOnly, Hidden'
The attributes may be toggled:
$file = Get-Item 'somefile.txt' $file.Attributes = $file.Attributes -bxor 'ReadOnly'
Attributes may be added:
$file = Get-Item 'somefile.txt' $file.Attributes = $file.Attributes -bor 'ReadOnly'
The operators +, -, +=, and -= may be used, as this is a numeric operation. Addition or subtraction operations are not safe, as they do not account for existing flags. For example, if a file was already read-only and += was used to attempt to make the file read-only, the result would be a hidden file:
PS> $file = Get-Item 'somefile.txt'
$file.Attributes = 'ReadOnly'
$file.Attributes += 'ReadOnly'
$file.Attributes
Hidden
Finally, regardless of whether or not a flag is present, attributes may be written as a string:
$file = Get-Item 'somefile.txt' $file.Attributes = "$($file.Attributes), ReadOnly"
This is a feasible approach because casting to the enumeration type will ignore any duplication:
PS> [System.IO.FileAttributes]'ReadOnly, Hidden, ReadOnly'
ReadOnly, Hidden