Figure 1
Running DIR in PowerShell also produces a directory listing like Figure 2, but it's a little different. PowerShell does not have a DIR command but instead has Get-ChildItem, which also performs the same function. In PowerShell, DIR is an alias for Get-ChildItem. I do not intend to go into detail about aliases in this article. You can think of DIR in PowerShell as an abbreviation for Get-ChildItem.
DIR in PowerShell provides much of the same information as mentioned above: a list of files and folders, the date and time of the last update and the size of each file. However, it lacks the summary information that DIR in CMD.EXE provides: total size of all files in the folder, total number of files and total number of subfolders.
Figure 2
For the example scenario, you will need to create a PowerShell script that simulates the CMD.EXE DIR command. Below I will explain the most essential parts of a script.
DIR.PS1: Header
A PowerShell script includes PowerShell commands in a plain text file with the .PS1 extension. Instead of DIR, you will use a text file called DIR.PS1.
To run the script, type the following command at the PowerShell screen:
.DIR.PS1 X:Folder
Where X is the drive partition letter (like C, D, E) and Folder is the folder name.
If you want to know some information about drive partitions, you will have to use Windows Management Instrumentation (WMI). Details about WMI are beyond the scope of this article so we will not discuss them here. But the PowerShell code below is quite easy to understand without needing WMI's help. You can create a '$filter' variable to use with the Get-WmiObject command. This filter variable tells the Get-WmiObject command that you only want information about a specific drive. The results of the Get-WmiObject command are stored in a variable called $volInfo. Remember, in PowerShell everything is an object; $volInfo is now also a result object returned from Get-WmiObject.
$filter = "DeviceID = '" + $drive + ":'" $volInfo = Get-WmiObject -Class Win32_LogicalDisk -Filter $filter
You can now access all the objects and methods associated with the object. The serial number of the drive partition can be accessed through the VolumeSerialNumber property. The returned information is an 8-character string of numbers. But usually you want to format it as four separate numbers, separated by a hyphen. can be done similarly as in the line below. The hyphen at the end of the first line is the line continuation character in PowerShell. It basically just tells PowerShell that the line doesn't break but includes the next line. Line separation is not necessary when writing code, but to reduce the width and make the code easier to read, you should do so.
$serial = $volInfo.VolumeSerialNumber.SubString(0, 4) + "-" + ` $volInfo.VolumeSerialNumber.SubString(4, 4)
Now that you have a $volInfo object, you can write the DIR header information to the screen. If the drive has no name, the text written to the screen will be slightly different than if the drive has a name. A simple If-Else statement is used to check whether the VolumeName property is an empty string or not. The Write-Host command is used to write each line of command to the screen.
If ($volInfo.VolumeName -eq "") { Write-Host (" Volume in drive " + $drive + " has no label") } Else { Write-Host (" Volume in drive " + $drive + " is " + $volInfo.VolumeName) } Write-Host (" Volume Serial Number is " + $serial) Write-Host ("`n Directory of " + $args[0] + "`n")
The ' `n ' character at the beginning and end of the Write-Host command is used to insert new lines before and after text. The Write-Host command adds a newline to the end of each line. So the effect of ' `n ' is to create blank lines before and after the line of text.
Did you notice the '-eq' in the If statement? It's an equality comparison operator. The table below shows you all the comparison operators:
-eq, -ieq | Compare equals |
-ne, -ine | Comparison is not equal |
-gt, -igt | Greater comparison |
-ge, -ige | Compare greater than or equal |
-lt, -ilt | Compare smaller |
-le, -ile | Compare less than or equal |
The -i character in front of comparison operators indicates that the operator is case-insensitive.
Figure 3: Output of the script you currently have
DIR.PS1: List of files/folders
Now you're ready to display the contents and properties of this folder. The first thing to do is call the PowerShell Get-ChildItem command to get the set of files and pass it to the script as a parameter. The Get-ChildItem command will retrieve a collection of file and folder objects, not just the names but also pipe these objects directly into the Sort-Object command to sort them. By default, the Sort-Object command will sort objects based on the Name attribute. So you don't need to describe any other parameters. The sorted collection of objects is then stored in a variable named $items.
$items = Get-ChildItem $args[0] | Sort-Object
Once you have a set of file and folder objects, you need to iterate over them and display the appropriate features. The command used for this is ForEach. For each file or folder, the displayed characteristics will be the date and time of the last update, name, length or file size. The strange thing that looks like strings of characters inside parentheses is the .NET string format code. They are used to left/right align fields and format dates, times, and numbers. Understanding these string format codes is not very important, because they are not essential to the nature of this script.
The If statement is where you determine whether any object is a directory or not. If the first character of the Mode attribute is 'd', the object is a directory. You need to double check because the code written for directories is often different from the code written for files.
Notice the $totalDirs++ line inside the If statement. This is the counter responsible for keeping track of directory numbers. Similarly, there is a $totalFiles variable that is used to track the total size of all files. These values are always calculated during execution. But they are only displayed when the file listing process is finished.
ForEach ($i In $items) { $date = "{0, -20:MM/dd/yyyy hh:mm tt}" -f $i.LastWriteTime $file = $i.Name If ($i.Mode.SubString(0, 1) -eq "d") { $totalDirs++ $list = $date + " {0, -15}" -f " " + " " + $file } Else { $totalFiles++ $size = "{0, 18:N0}" -f $i.Length $list = $date + $size + " " + $file } $totalSize += $i.Length Write-Host $list }
Figure 4: Displaying the output data of the updated script.
DIR.PS1: Footer
The only thing left is to write on the screen the total number of files, folders, total size of all files and free space on this drive partition. To do this you will need to use the counter variables ($totalFiles, $totalDirs, $totalSize) created in the previous section. You can know the amount of free space from the $volInfo variable created at the beginning of the script.
Write-Host ("{0, 16:N0}" -f $totalFiles + " File(s)" + ` "{0, 15:N0}" -f $totalSize + " bytes") Write-Host ("{0, 16:N0}" -f $totalDirs + " Dir(s)" + ` "{0, 16:N0}" -f $volInfo.FreeSpace + " bytes free`n")
Figure 5: Complete display of the script's output data.
Enhanced forecasts and capabilities are possible
Although the script you create produces nearly identical output to the CMD.EXE DIR command, there are some predictions you need to be aware of and some enhancements that can be made.
Conclude
Although PowerShell is a powerful utility and scripting language, it only takes a little time to grasp and use it, especially if you are not familiar with the .NET Framework environment. I hope this article with its example script will be useful to anyone who wants to understand PowerShell. But the script created as an example in the article is quite simple. Believe that it can be built and developed more completely to serve more complex applications well.