Welcome PowerShell User! This recipe is just one of the hundreds of useful resources contained in the PowerShell Cookbook.

If you own the book already, login here to get free, online, searchable access to the entire book's content.

If not, the Windows PowerShell Cookbook is available at Amazon, or any of your other favourite book retailers. If you want to see what the PowerShell Cookbook has to offer, enjoy this free 90 page e-book sample: "The Windows PowerShell Interactive Shell".

6.4 Work with Numbers as Binary

Problem

You want to work with the individual bits of a number or work with a number built by combining a series of flags.

Solution

To directly enter a hexadecimal number, use the 0x prefix:

PS > $hexNumber = 0x1234
PS > $hexNumber
4660

To convert a number to its binary representation, supply a base of 2 to the [Convert]::ToString() method:

PS > [Convert]::ToString(1234, 2)
10011010010

To convert a binary number into its decimal representation, use the binary prefix 0b:

$myBinary = 0b10011010010

If you have the value as a string, supply a base of 2 to the [Convert]::ToInt32() method:

PS > [Convert]::ToInt32("10011010010", 2)
1234

To manage the individual bits of a number, use PowerShell’s binary operators. In this case, the Archive flag is just one of the many possible attributes that may be true of a given file:

PS > $archive = [System.IO.FileAttributes] "Archive"
PS > attrib +a test.txt
PS > Get-ChildItem | Where { $_.Attributes -band $archive } | Select Name

Name
----
test.txt
PS > attrib -a test.txt
PS > Get-ChildItem | Where { $_.Attributes -band $archive } | Select Name
PS >

Discussion

In some system administration tasks, it’s common to come across numbers that seem to mean nothing by themselves. The attributes of a file are a perfect example:

PS > (Get-Item test.txt).Encrypt()
PS > (Get-Item test.txt).IsReadOnly = $true
PS > [int] (Get-Item test.txt -force).Attributes
16417
PS > (Get-Item test.txt -force).IsReadOnly = $false
PS > (Get-Item test.txt).Decrypt()
PS > [int] (Get-Item test.txt).Attributes
32

What can the numbers 16417 and 32 possibly tell us about the file?

The answer to this comes from looking at the attributes in another light—as a set of features that can be either true or false. Take, for example, the possible attributes for an item in a directory shown by Example 6-3.

Example 6-3. Possible attributes of a file
PS > [Enum]::GetNames([System.IO.FileAttributes])
ReadOnly
Hidden
System
Directory
Archive
Device
Normal
Temporary
SparseFile
ReparsePoint
Compressed
Offline
NotContentIndexed
Encrypted
IntegrityStream
NoScrubData

If a file is ReadOnly, Archive, and Encrypted, then you might consider the following as a succinct description of the attributes on that file:

ReadOnly = True
Archive = True
Encrypted = True

It just so happens that computers have an extremely concise way of representing sets of true and false values—a representation known as binary. To represent the attributes of a directory item as binary, you simply put them in a table. We give the item a 1 if the attribute applies to the item and a 0 otherwise (see Table 6-1).

Table 6-1. Attributes of a directory item
Attribute True (1) or false (0)

Encrypted

1

NotContentIndexed

0

Offline

0

Compressed

0

ReparsePoint

0

SparseFile

0

Temporary

0

Normal

0

Device

0

Archive

1

Directory

0

<Unused>

0

System

0

Hidden

0

ReadOnly

1

If we treat those features as the individual binary digits in a number, that gives us the number 100000000100001. If we convert that number to its decimal form, it becomes clear where the number 16417 came from:

PS > 0b100000000100001
16417

This technique sits at the core of many properties that you can express as a combination of features or flags. Rather than list the features in a table, though, the documentation usually describes the number that would result from that feature being the only one active—such as FILE_ATTRIBUTE_REPARSEPOINT = 0x400. Example 6-4 shows the various representations of these file attributes.

Example 6-4. Integer, hexadecimal, and binary representations of possible file attributes
PS > $attributes = [Enum]::GetValues([System.IO.FileAttributes])
PS > $attributes | Select-Object `
   @{"Name"="Property";
       "Expression"= { $_ } },
   @{"Name"="Integer";
       "Expression"= { [int] $_ } },
   @{"Name"="Hexadecimal";
       "Expression"= { [Convert]::ToString([int] $_, 16) } },
   @{"Name"="Binary";
       "Expression"= { [Convert]::ToString([int] $_, 2) } } |
   Format-Table -auto


         Property Integer Hexadecimal Binary
         -------- ------- ----------- ------
         ReadOnly       1 1           1
           Hidden       2 2           10
           System       4 4           100
        Directory      16 10          10000
          Archive      32 20          100000
           Device      64 40          1000000
           Normal     128 80          10000000
        Temporary     256 100         100000000
       SparseFile     512 200         1000000000
     ReparsePoint    1024 400         10000000000
       Compressed    2048 800         100000000000
          Offline    4096 1000        1000000000000
NotContentIndexed    8192 2000        10000000000000
        Encrypted   16384 4000        100000000000000
  IntegrityStream   32768 8000        1000000000000000
      NoScrubData  131072 20000       100000000000000000

Knowing how that 16417 number was formed, you can now use the properties in meaningful ways. For example, PowerShell’s -band operator allows you to check whether a certain bit has been set (assuming that you’ve set test.txt to be encrypted through either the Explorer UI or other means):

PS > $encrypted = 16384
PS > $attributes = (Get-Item test.txt -force).Attributes
PS > ($attributes -band $encrypted) -eq $encrypted
True

PS > $compressed = 2048
PS > ($attributes -band $compressed) -eq $compressed
False

Although that example uses the numeric values explicitly, it would be more common to enter the number by its name:

PS > $archive = [System.IO.FileAttributes] "Archive"
PS > ($attributes -band $archive) -eq $archive
True

For more information about PowerShell’s binary operators, see “Simple Operators”.

See Also

“Simple Operators”