≡ Menu

PowerShell: Get unique values from array

This post is about finding unique values from PowerShell array by removing redundant/duplicate items. We will discuss various options available to list the unique values in array and their benefits/downsides.

There are multiple ways to do this.

  1. Get-Unique cmdlet
  2. Select-Object cmdlet
  3. Sort-Object cmdlet (the winner)

Get-Unique

This is the most well known and famous option. It is because of intuitiveness in the name. But many feel it is cumbersome to use and some couldn’t figure out how to use this. This is because Get-Unique cmdlet works by comparing each item in sorted list to the next item to eliminate the duplicates. That means if you plan to use this cmdlet you need to make sure the input list of sorted. Also this cmdlet is case-sensitive. See what happens when I pass array of duplicate items to this to get the unique ones.

As you noticed in the output, it returned everything in the array. It because they differ by case. So you need to convert everything to lowercase/upper case, sort it, and then pass to this cmdlet to get the actual result.

Is there no other easy way? Yes, read on…

Select-Object

Let us see what happens when we pass the same array to select-object cmdlet by specifying -Unique cmdlet.


$letters = @("A","a","b","c","F","c","a","E","d")

$letters | select -unique

As you can see it worked better than Get-Unique but it still failed to match items which are different in case. The -Unique switch of Select-Object looks for duplicate items through out the list to remove them. But it does case sensitive search to do that. So, you need to convert the list to lower or upper case before passing it to select-object to get unique items.

Sort-Object

Looking at the name of the cmdlet, you might wonder whether it will really remove the duplicates. But it does and does better job than other two above. Now let us pass the same array to Sort-Object by specifying the -Unique switch.


$letters = @("A","a","b","c","F","c","a","E","d")

$letters | sort -unique

 

Hurray.. it worked. It searched for duplicate items throughout the list and removed the duplicates irrespective of case. This is what most of the systems need when they want to remove duplicates from array using PowerShell.

 

{ 0 comments }

Telnet using PowerShell

Ever since telnet client is not enabled by default in Windows Server 2008(also in 2012 and 2016), SysAdmins has tough time using telnet command when they need it. In this post, let us see what are the options for us to telnet without using actual telnet.exe

We have two options when there is no telnet.exe command.

  • Using .Net classes to perform the telnet
  • Using Test-NetConnection cmdlet (available from Windows Server 2012 onward)

Using .Net Classes to perform the telnet

The System.Net.Sockets.TCPClient class provides facility to perform telnet operation to remote host on specified port. I have posted about this in past with the title Test Port Connectivity using PowerShell. This article has a function which you can import into your shell and use it to perform the telnet operation.

This method works for all versions of windows operating systems as it is using underlying .Net Module.

Using Test-NetConnection cmdlet

Starting Windows Server 2012, Microsoft has provided a inbuilt function for this purpose. It is called Test-NetConnection. This function can be used to perform telnet, traceroute and many other operations. In this post I will limit the discussion to telnet functionality.

To telnet to a port on remote computer you have to use –ComputerName and –Port parameters of this function. For example, if you want to check if google.com is responding on port 80, then use below command.


Test-NetConnection -ComputerName google.com -Port 80

After completing the execution, it returns an object which will tell you the output of the telnet. The TCPTestSucceeded value will be True if the telnet is successful and will be False if the telnet has failed.

Look at the below screenshots for understanding this.

Telnet Successful:

Telnet Failure:

As mentioned before this works on Windows Server 2012 or above only. If you need same thing for previous versions you need to use the first approach that I mentioned.

Hope this helps.

{ 2 comments }

It is a very common requirement to have just file name extracted from full path while working on your PowerShell scripts. For example, your script received a file full path(c:\abc\xyz\test.txt) and you want to just get the file name from it with or without extension(ex: test or test.txt). In this post how to achieve this.

There are several ways to do this. For example, a programmer with good regex knowledge tend to write a regex to extract the file name. Or you can also use Split-Path cmdlet in PowerShell do this. The approach I am going to share here is based on .Net classes and my favourite approach. I am not against using cmdlets but thing is they also internally use the .Net classes. So why not use them directly?

Get File name from full path.

[System.IO.Path]::GetFileName("C:\abc\xyz\test.txt")

Get File name with extension from full path

[System.IO.Path]::GetFileNameWithoutExtension("C:\abc\xyz\test.txt")

As you can see I am using System.IO.Path classes to perform this work. You can explore the other methods available in these modules and there are many useful functions.

 

{ 4 comments }

Add a file to existing ZIP file using PowerShell

One of the popular posts on this blog about managing ZIP/compressed/Archived Files is reading the contents from ZIP file. Several people asked how to add a file to existing ZIP file using PowerShell which I will cover in this blog post.

We will be using System.IO.Compression.FileSystem Assembly which contains the required classes to open an existing ZIP file and add new files to it. We have used the same assembly to read the contents of the ZIP file. To perform the add operation to existing zip file, we first need to open the ZIP file in Update mode and then add new file using CreateEntryFromFile method in System.IO.Compression.ZipFileExtension class. Don’t worry much about these classes and methods. I mentioned them for your understanding. You can explore further using these classes if you have any other requirements in managing the ZIP files.

Let us jump into the code now.

Code:


[CmdletBinding()]
Param(
[string]$ZIPFileName,
[string]$NewFileToAdd
)

try {
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null
$zip = [System.IO.Compression.ZipFile]::Open($ZIPFileName,"Update")
$FileName = [System.IO.Path]::GetFileName($NewFileToAdd)
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$NewFileToAdd,$FileName,"Optimal") | Out-Null
$Zip.Dispose()
Write-Host "Successfully added $NewFileToAdd to $ZIPFileName "
} catch {
Write-Warning "Failed to add $NewFileToAdd to $ZIPFileName . Details : $_"

}

Usage:

Now let us see how to use this script. Save the above code into a file(Add-ToZipFile.ps1) or download the script from GitHub(https://github.com/techibee/PowerShell/blob/master/Add-ToZIPFile.ps1) and start using it with below example.

Add c:\test.txt to c:\myzip.zip file


PS C:\> .\Add-ToZIPFile.ps1 -ZIPFileName C:\myzip.zip -NewFileToAdd C:\test.txt

Hope this helps. I will add more examples related to zip files and Powershell in upcoming days.

{ 0 comments }

Get current directory using Python

In today’s post we will see how to find current directory(or working directory) using python. Current directory is nothing but the folder from where your script is running. This is not the path where your py script is located, but we will explore how to find it as well.

Get the path of current working directory

To accomplish this task we will use os module in python. It has a method called getcwd() which will return current working directory. It is that simple. It returns full path(absolute) of the current working directory. If you want just the directory name then either you can split by “/” or use another function called basename from os.path module.

Below is the code that returns both absolute path of the current working directory and its name.


import os

dirpath = os.getcwd()
print("current directory is : " + dirpath)
foldername = os.path.basename(dirpath)
print("Directory name is : " + foldername)

Copy the above code into a file and save it as get_path.py and run it to see the results.

As you can see in the above screen, the script(get_path.py) is stored in python directory. When ran this script from same directory as script it returned the directory name as python. Same script when ran from another directory(Documents) using relative path, it returned the directory name as Documents. So it always returns the current working directory from where your script is triggerred.

Get the path of script file

Now let us see how to get the path of script it self irrespective of from where you are running it. For this purpose we will utilise the special variable called __file__ and pass it to realpath method of os.path module.


import os

dirpath = os.getcwd()
print("current directory is : " + dirpath)
foldername = os.path.basename(dirpath)
print("Directory name is : " + foldername)
scriptpath = os.path.realpath(__file__)
print("Script path is : " + scriptpath)

Copy the above code into a file and execute it to see the results. In the below demonstration, I have executed it from another directory using the relative path and you see that script location is being displayed properly.

As you can see in the screenshot, the script path is being displayed.

Hope this helps and stay tuned for more.

{ 0 comments }

Find version of python your script is running on

Sometimes your python scripts requires minimum version of python as a few things keeps changing from version to version. If your script is using any of such facilities it is important to ensure that the python version you are using is exactly same(or minimum version).

There are many ways to find this information. However, I will show you the basic one.


import sys

version = sys.version_info
print("Major version is : {0}".format(version.major))
print("Minor version is : {0}".format(version.minor))

Executing the above code will show the version number of python using which the script is running. For demonstration purpose, I have copied the above code into a file called test_pyversion.py file and executed with different versions of python.

In above screen my default version of python is 2.7 and python3 is pointing to python 3.5. When I ran the script using python 2.7 and python 3.5, it displayed the version numbers.

You can use a simple if condition inside the script to check the required version number and exit it if required version not found.

Hope you will find this useful.

{ 0 comments }

Find OS images inside WIM file using PowerShell

WIM(Windows Imaging Format) file can contain one or more images based on how it was prepared. The Operating System ISO file provided by Microsoft will have WIM file with several images init for different versions of operating system. The purpose of this post is to show you how to see the images inside it.

In this case ISO file is mounted to D: drive so the path of Install.wim file is D:\Sources\Install.wim

Get-WindowsImage -ImagePath D:\Sources\Install.wim

This will list images inside the ISO file. The output of above command gives output similar to below.

 

Hope this helps.

 

{ 0 comments }

Mount a image file(WIM) using Powershell

Sometimes you are required to Mount WIM (Windows Image Format) files to perform actions like reading the content or updating the image itself. DISM.exe is a very good utility to perform these from command line.  Starting Windows 8/Windows Server 2012 Microsoft added a new PowerShell module called DISM. Now we will see how to use that module to mount a WIM image.

Mount-WindowsImage cmdlet in DISM module has the functionality to mount a WIM file to one of the directory on the file system.  You can run below command to mount install.wim file from installation media to c:\installsource folder.

Mount-WindowsImage -ImagePath D:\Sources\Install.WIM -Index 2 -Path C:\InstallSource -ReadOnly

 

Here, D:\Sources\Install.WIM is the image file, Index is used to identify the OS from the list you have in image file. Path is to specify the mount directory on the file system. -ReadOnly specifies that no changes should be saved or committed to the WIM file.

 

{ 0 comments }

Hide Acrobat Reader Tool bar in Mac/Windows

Side bar(Tool bar) that appears with Adobe Acrobat Reader with options like Export PDF, Create PDF, Edit PDF, etc, is frustrating sometimes as you don’t find a way to close/minimise it. When reading any PDF files, it is taking at least 30% of the screen space.

Acrobat Reader RC disable Tool pane

There is an option to disable this tools pane but it is not working as expected. If you want you can try it as well by following the below instructions.

  1. Go to Edit > Preferences (or press Ctrl+K in Windows and Command+K in Mac)
  2. Go inside “Documents” section
  3. uncheck “Open tools pane for each document”.

There are some forums which are advising to edit a XML file to get rid of this tool bar pane, but for a normal user they are little complex.

One quick and easy way that I came across is a key combination. See below based on your operating system.

Windows : SHIFT + F4

MAC : SHIFT+Fn+F4

Pressing above key combination toggles the tool bar pane in acrobat reader. So you can easily enable or disable as you need.

{ 1 comment }

PowerShell: How to query date time without seconds

How many times you got a need for querying the date time variable using Get-Date or [DateTime]:Now but without seconds value in it or making it as 00 seconds? Let us find out what are the options to achieve this using PowerShell.

By default Get-Date cmdlet gives seconds as well. In some cases we feel reading till minutes is sufficient or we want to round off to 00 seconds. This is possible if you decide to convert time value to a string as shown below.

$datetime = Get-Date -Format “yyyyMMddHHmm”

[datetime]::ParseExact($datetime,“yyyyMMddHHmm”,$null)

While this is good, I was looking for better approaches to do this without actually converting it to a string. Lucky I came across one.

This approach is simple which deducts seconds from current date time value to make it zero.

$datetime = Get-Date

$datetime.AddSeconds($datetime.Second)

date-time-without-seconds

Hope you liked it.

{ 2 comments }