Saturday, June 20, 2009

Unix Equivalents in Powershell

I come from Linux background which I really like . There are lot more utilities in Unix/Linux which provide more convenient way of doing some work. They are really very useful in speeding up the work and automating repetitive tasks.

Since the release of Windows Powershell, it has proven to be one of the most powerful shells available now.

As I started using Powershell, I find myself most of the times searching for UNIX equivalents in windows powershell. Here are a few which i came across

wc in Powershell: Measure-Object


[jagadish.g@localhost Scripts]$ cat test.csv | wc
4 13 277
[jagadish.g@localhost Scripts]$ cat test.csv | wc -l
4


PS C:\Scripts> Get-Content test.csv | Measure-Object -line -word -character

Lines Words Characters Property
----- ----- ---------- --------
4 13 273

PS C:\Scripts> Get-Content test.csv | Measure-Object -line

Lines Words Characters Property
----- ----- ---------- --------
4

time in Powershell: Measure-Command


[jagadish.g@localhost Scripts]$ time sleep 5

real 0m5.003s
user 0m0.000s
sys 0m0.001s


PS C:\Scripts> Measure-Command { Sleep 5 }

Days : 0
Hours : 0
Minutes : 0
Seconds : 4
Milliseconds : 999
Ticks : 49996681
TotalDays : 5.78665289351852E-05
TotalHours : 0.00138879669444444
TotalMinutes : 0.0833278016666667
TotalSeconds : 4.9996681
TotalMilliseconds : 4999.6681

GREP in Powershell: Select-String


[jagadish.g@localhost Scripts]$ cat test.csv | grep "Tony Passaquale"
1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up


PS C:\Scripts> Get-Content test.csv | Select-String "Tony Passaquale"

1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up

NOTE, Select-String is Case-Insensitive by default. Use -CaseSensitive switch parameter to make it case sensitive.

Now lets try to get one line after the line with the match


[jagadish.g@localhost Scripts]$ cat test.csv | grep -A1 "Tony Passaquale"
1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity


PS C:\Scripts> Get-Content test.csv | Select-String "Tony Passaquale" -Context 0,1

> 1,Tony Passaquale,7920,20090222 21:59:00,800,4.78,3824,Follow-up
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity

The -Context parameter in the Select-String cmdlet is used to capture the specified number of lines before and after the line with the match. If you look at the above code window, I have passed '0,1' value to the -Context parameter. The first integer specifies the number of lines to print before the match (in this case, it is 0) and the next integer specifies the number of lines to print after the match (in this case, it is 1)

Select-String cmdlet is using regular expression matching by default. So you can use use regex patterns to select the required lines.


[jagadish.g@localhost Scripts]$ cat test.csv | grep "y$"
2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity
4,Allen James,95140,20090405 16:31:00,1000,9.99,9990,New-Opportunity


PS C:\Scripts> Get-Content test.csv | Select-String "y$"

2,Nigel Shan Shanford,30316,20090405 16:34:00,400,9.99,3996,New-Opportunity
4,Allen James,95140,20090405 16:31:00,1000,9.99,9990,New-Opportunity

AWK in Powershell

Powershell has lot of features and abilities for text parsing. AWK is one of very powerful commands available for text parsing in Unix/Linux. We do not have a Awk like cmdlet in Powershell. But we can do everything in Powershell that can be done with Awk.

Powershell combined with .Net Classes provide very powerful regular expressions for text parsing. read more...

cd - in Powershell

One of the cool features of linux bash is the ability to go to the previous working directory. In Bash, we can go to the previous working directory using "cd -" command.

Unfortunately, we do not have an equivalent of "cd -" in Powershell. So I just wrote a simple powershell function for this cool feature. read more...

find command in Powershell

Find is one of the most often used commands in day to day work life. Unix find command provides lot of features and options that enable users to find files/directories more effectively

In Powershell, we can use Get-ChildItem cmdlet to search for files. But it doesn't give you all the fun. So I have developed Find-ChildItem Powershell cmdlet which is equivalent to Unix find command. read more...

16 comments:

  1. Have you tried:
    Get-Service | Select-String "Running"?

    ReplyDelete
    Replies
    1. This doesn't appear to work.

      Delete
  2. It is highly redundant and bad scripting to run cat with grep or awk.
    Better use grep "y$" test.csv

    ReplyDelete
  3. I recommend Skype Call Recorder. Helps me a lot for recording interviews, podcasts

    ReplyDelete
  4. Walter, agreed. Also took me a while to realize that using grep before awk was usually redundant, when...

    grep "y$" test.csv | awk -F , '{print $1}'

    ...is the equivalent of...

    awk -F , '/y$/ {print $1}'

    (Sorry if I screwed up any of the syntax. It has been a while.)

    ReplyDelete
  5. Oops! I see at least one screw-up already. That last command was missing a file name, so it should (at least) have read...

    awk -F , '/y$/ {print $1}' test.csv

    ReplyDelete
  6. for a 90MB file, Measure-Object -line -word -character takes a minute, while cygwin's wc takes 2 seconds. Jeesh

    ReplyDelete
  7. for find I just use "get-childitem | ?{$_.(something you care about) -is "What you want"}"

    ReplyDelete
  8. Powershell really is junk. Take my advice... If you have to perform any real scripting work use cygwin or do it on a *nix platform.

    ReplyDelete
    Replies
    1. Talked nonsense because he lacked knowledge. Supporter team does the same.

      Delete
  9. Thank you, but I won't take your advice :))

    ReplyDelete
  10. Get-Service | where { $_.Status -match "Running" }

    ReplyDelete
    Replies
    1. good reply sir. actually this particular item is returned by PS as example if we type man get-service -full. This last bit -full is quite useful.

      Delete
  11. (Get-Content test.csv | Select-String "Tony Passaquale" -Context 0,1)

    You can do that, but with PowerShell use Objects whenever you can. So, (Import-Csv test.csv | Where-Object {$_.name -eq 'Tony Passaquale'}) is more fun for me.

    ReplyDelete