Tuesday, September 26, 2017

Objects. One of many ways PowerShell differs from Unix shells

In learning Powershell, one of the hardest things to wrap my head around is how it is, and is not, like Unix shells. While it does allow you to interact with your system and perform actions, such as running commands, executing scripts, or doing the same to remote systems, there are some differences. Like... everything is an object, instead of everything is a blob of text. This has taken some getting used to, but in many ways it really simplifies a lot of activities that in a Unix shell would take a pretty complex pipeline.

People often conflate the Unix shell, such as Bash, or Zsh, and the terminal, such as xterm, Gnome Terminal, iTerm, etc. The terminal is the application or hardware through which a user can interact with the Unix system. Back in the last millenium, the terminal started off as a teletypewriter, from which modern Unix and Unix-like operating systems still retain the 'tty' name. Nowadays, it's also common to see purely software implementations referred to as pseudo-terminals (pty), because they serve the same function but have no physical manifestation, which are used by Terminal Emulators. The shell that runs in the terminal is how users truly interact with the system. Bash, Zsh, Csh, Ksh, and their many derivatives or specialized shells (such as may be used at a car dealer, or a POS system, etc), are the utility through which the terminal becomes useful.

The only difference between a bash shell on the system console, tty0, and a bash shell running in a terminal emulator on a remote system connected via ssh, is the capabilities of the terminal to display output, and control input. The bash shell itself will be the same, and generally speaking, everything in the Unix shell is text. We run a command, such as `ls`, and we get back a blob of text that we, as humans, can interpret as a list of files and directories. We can further process, or parse, that text using tools like awk, sed, grep, etc. These additional tools allow us to filter output, take an action on a string in the output, count the number of items, etc, etc.

In the PowerShell ecosystem, the analog of the Terminal is the Host. Microsoft includes the "Console Host", which is the terminal-like window that opens if you run "Microsoft Powershell", and the "Windows Powershell ISE Host", which opens when you run the "Windows PowerShell ISE" application. Both of these windows serve as hosts for the PowerShell shell itself, and they actually provide different behaviors, too as far as output, debugging, etc. In PowerShell, everything is an object. When you run the date alias in PowerShell, you are presented a string representation of the current date and time, but that's just the display. What you actually get back is a [System.Datetime] or (shortened) [datetime]
object, which has all sorts of methods, properties, and metadata associated with it.

Here's an example just using the date command in bash on Linux:

tim@bash:~$ date
Tue Sep 26 11:13:38 DST 2017
tim@bash:~$ $(date)
Tue: command not found
tim@bash:~$ echo $(date)
Tue Sep 26 11:13:48 DST 2017

As you can see, the output of the date command is a string. There is no metadata or properties associated with a datestamp or timestamp, because we just have a string. Here is PowerShell's date:

tim@PS > date
Tuesday, September 26, 2017 11:19:30 AM

tim@PS > (date) | Get-Member

   TypeName: System.DateTime

Name                 MemberType     Definition
----                 ----------     ----------
Add                  Method         datetime Add(timespan value)
AddDays              Method         datetime AddDays(double value)
AddHours             Method         datetime AddHours(double value)
AddMilliseconds      Method         datetime AddMilliseconds(double value)
AddMinutes           Method         datetime AddMinutes(double value)
AddMonths            Method         datetime AddMonths(int months)
AddSeconds           Method         datetime AddSeconds(double value)
AddTicks             Method         datetime AddTicks(long value)
AddYears             Method         datetime AddYears(int value)
CompareTo            Method         int CompareTo(System.Object value), int ...
Equals               Method         bool Equals(System.Object value), bool E...
GetDateTimeFormats   Method         string[] GetDateTimeFormats(), string[] ...
GetHashCode          Method         int GetHashCode()
GetObjectData        Method         void ISerializable.GetObjectData(System....
GetType              Method         type GetType()
GetTypeCode          Method         System.TypeCode GetTypeCode(), System.Ty...
IsDaylightSavingTime Method         bool IsDaylightSavingTime()
Subtract             Method         timespan Subtract(datetime value), datet...
ToBinary             Method         long ToBinary()
ToBoolean            Method         bool IConvertible.ToBoolean(System.IForm...
ToByte               Method         byte IConvertible.ToByte(System.IFormatP...
ToChar               Method         char IConvertible.ToChar(System.IFormatP...
ToDateTime           Method         datetime IConvertible.ToDateTime(System....
ToDecimal            Method         decimal IConvertible.ToDecimal(System.IF...
ToDouble             Method         double IConvertible.ToDouble(System.IFor...
ToFileTime           Method         long ToFileTime()
ToFileTimeUtc        Method         long ToFileTimeUtc()
ToInt16              Method         int16 IConvertible.ToInt16(System.IForma...
ToInt32              Method         int IConvertible.ToInt32(System.IFormatP...
ToInt64              Method         long IConvertible.ToInt64(System.IFormat...
ToLocalTime          Method         datetime ToLocalTime()
ToLongDateString     Method         string ToLongDateString()
ToLongTimeString     Method         string ToLongTimeString()
ToOADate             Method         double ToOADate()
ToSByte              Method         sbyte IConvertible.ToSByte(System.IForma...
ToShortDateString    Method         string ToShortDateString()
ToShortTimeString    Method         string ToShortTimeString()
ToSingle             Method         float IConvertible.ToSingle(System.IForm...
ToString             Method         string ToString(), string ToString(strin...
ToType               Method         System.Object IConvertible.ToType(type c...
ToUInt16             Method         uint16 IConvertible.ToUInt16(System.IFor...
ToUInt32             Method         uint32 IConvertible.ToUInt32(System.IFor...
ToUInt64             Method         uint64 IConvertible.ToUInt64(System.IFor...
ToUniversalTime      Method         datetime ToUniversalTime()
DisplayHint          NoteProperty   DisplayHintType DisplayHint=DateTime
Date                 Property       datetime Date {get;}
Day                  Property       int Day {get;}
DayOfWeek            Property       System.DayOfWeek DayOfWeek {get;}
DayOfYear            Property       int DayOfYear {get;}
Hour                 Property       int Hour {get;}
Kind                 Property       System.DateTimeKind Kind {get;}
Millisecond          Property       int Millisecond {get;}
Minute               Property       int Minute {get;}
Month                Property       int Month {get;}
Second               Property       int Second {get;}
Ticks                Property       long Ticks {get;}
TimeOfDay            Property       timespan TimeOfDay {get;}
Year                 Property       int Year {get;}
DateTime             ScriptProperty System.Object DateTime {get=if ((& { Set...

Just look at all those properties and methods that are automatically associated with a [datetime] object.

tim@PS > (date).ToShortDateString()

tim@PS > (date).ToLongDateString()
Tuesday, September 26, 2017

tim@PS > (date).ToUniversalTime()

Tuesday, September 26, 2017 3:21:53 PM

tim@PS > (date).IsDaylightSavingTime()

tim@PS > (date).AddYears(5)

Monday, September 26, 2022 11:22:29 AM

tim@PS > (date).AddMinutes(27)

Tuesday, September 26, 2017 11:49:54 AM

PowerShell feels a bit like a mix of Perl (syntax) and Python (everything is an object), presented as an interactive shell (with a bunch of familiar feeling Linux-ish aliases preconfigured).

Next Up... Output

No comments:

Post a Comment