Hey, Scripting Guy! How Can I Check for the Presence or Absence of a Text File?

ScriptingGuy1

Share this post:

 

Hey, Scripting Guy! QuestionHey, Scripting Guy! We use text files in special folders to determine if we have performed an operation on a computer. For example, we might install a piece of software on a computer. While it is possible to query the Win32_Product WMI class to determine if the software has been installed or to query the registry, it is much easier to simply see if a text file is present in a specific folder. If the text file is present, we have installed the software. This is an idea I had a long time ago when working with Systems Management Server (SMS). I would do a query to see if the text file exists.

I would like to have a Windows PowerShell script that will check for the existence of a text file. If the file does not exist, I would like to create the text file. If the file does exist, I would like to be notified. I could then modify such a script to work with my existing infrastructure. Can you provide me with a sample Windows PowerShell script that will do this?

— EC

Hey, Scripting Guy! Answer

Hello EC, Microsoft Scripting Guy Ed Wilson here.

A long time ago, back when I was a consultant in Cincinnati, Ohio, in the United States, I did a number of SMS 1.0 deployments. After I got my Microsoft Certified Trainer (MCT) certification, I even taught SMS classes. Over the years, I continued to work with SMS up to version 2.0. It was a fun and interesting product. One day, I hope to begin working with Microsoft System Center (the replacement for SMS) because it looks like a pretty cool product. So, EC, I know exactly what you are talking about when you mention looking for the presence of a file. We used to call such a file a canary file back in the days when I was working with SMS. I was looking around in the Hey, Scripting Guy! archives, and found the How Can I Determine If a File Exists and If It does, Exit the Script? article.  This article was written using the FileSystemObject and VBScript. You could duplicate it in Windows PowerShell using the FileSystemObject, but there is no reason to do this because Windows PowerShell has the Test-Path cmdlet that is designed to check for the existence of things.

EC, I wrote the DetermineIfFileExists.ps1 script for you. It will check the existence of a specific file, and if the file does not exist, it will create the file for you. Inside the file, it will record the current time. If the file does exist, the script displays a small message on the Windows PowerShell console, and then the script will exit. The complete DetermineIfFileExists.ps1 script is seen here.

DetermineIfFileExists.ps1

$path = “c:\fso\IwasHere.txt”

If(-not(Test-Path -path $path))
  {
    New-Item -Path $path -ItemType file -Value $(Get-Date) -force
  }
Else
 { “File exists” ; exit }

The DetermineIfFileExists.ps1 script begins by using the $path variable to hold the path to a specific file. The file in this case is called IwasHere.txt, and it should be located in the FSO folder on the C:\ drive. As seen in the following image, the text file does not exist:

Image of IwasHere.text file not yet in C:\Fso


The line of code that holds the path to the text file is seen here:

$path = “c:\fso\IwasHere.txt”

The Test-Path cmdlet is used to determine if the text file exists. When using the Test-Path cmdlet, it is important to realize that it only returns true or false. As seen here, the Test-Path cmdlet is used to determine if there is a file named 1234.txt in the C:\fso folder. The 1234.txt file does in fact exist (as shown in the image above), and therefore the Test-Path cmdlet returns true:

PS C:\> Test-Path -Path C:\fso\1234.txt
True
PS C:\>

If you want to evaluate the returned Boolean value, you can use the If statement to evaluate the true/false values that are returned by the Test-Path cmdlet. This technique is shown here:

PS C:\> If((Test-Path -Path C:\fso\1234.txt) -eq $true) { “The file exists” }
The file exists
PS C:\>

A better approach to dealing with the Boolean value returned value by the Test-Path cmdlet is to not use the equality operator (-eq). Because the return value is true/false, you can say (in effect), “If the file exists, do something.” This is shown here:

PS C:\> If(Test-Path -Path C:\fso\1234.txt) { “The file exists” }
The file exists
PS C:\>

The “if the file exists” technique works great if you are interested in the existence of the file, but what if you want to know if the file does not exist? You could go back to specifically evaluating the true/false condition and look for false as shown here:

PS C:\> If((Test-Path -Path C:\fso\1234.txt) -eq $false) { “File does notexist” }
PS C:\>

But a better approach is to use the –not operator inside the If/Test-Path condition. This is the approach that was taken with the DetermineIfFileExists.ps1 script. The code is shown here:

If(-not(Test-Path -path $path))

The one thing to keep in mind is the placement of the parentheses. Because you want to evaluate the return code from the Test-Path cmdlet, you need to ensure the Test-Path cmdlet runs first. To do this, it is placed inside a set of parentheses. After the Boolean return value is returned, the –not operator is evaluated. If the file does not exist, the file will be created by using the New-Item cmdlet, which is used to create new items.

The type of item it will create depends upon the Windows PowerShell provider that is used. In this example, because you are working with the file system, you are using the FileSystem provider. The Windows PowerShell FileSystem provider is capable of creating two different types of items—a file or a directory. Because of this, you must specify a value for the –ItemType parameter. The –path parameter is used to tell the cmdlet where to create the new item. The path can be local, or it can be located on a remote computer by using a Universal Naming Convention (UNC) path such as \\remotecomputername\remotesharename\filename.  To illustrate using UNC, first ping a remote computer. After determining that the remote computer is available, use the New-Item cmdlet to create a file. After the file has been created, use the Get-ChildItem cmdlet to ensure that the file is present on the remote computer. The use of UNC paths is seen here:

PS C:\> ping hyperv

Pinging HyperV.NWTraders.Com [192.168.1.100] with 32 bytes of data:
Reply from 192.168.1.100: bytes=32 time=1ms TTL=128
Reply from 192.168.1.100: bytes=32 time=1ms TTL=128
Reply from 192.168.1.100: bytes=32 time=1ms TTL=128
Reply from 192.168.1.100: bytes=32 time<1ms TTL=128

Ping statistics for 192.168.1.100:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 1ms, Average = 0ms
PS C:\> New-Item -Path \\hyperv\c$\fso\myfile.txt -Force -ItemType file


    Directory: \\hyperv\c$\fso


Mode                LastWriteTime     Length Name
—-                ————-     —— —-
-a—         9/15/2009   5:20 PM          0 myfile.txt


PS C:\> Get-ChildItem -Path ‘\\hyperv\c$\fso’


    Directory: \\hyperv\c$\fso


Mode                LastWriteTime     Length Name
—-                ————-     —— —-
-a—         9/15/2009   5:20 PM          0 myfile.txt


PS C:\>

In the DetermineIfFileExists.ps1 script the New-Item cmdlet is used to create a new file. The initial value (the contents of the newly created text file) is created by using a subexpression to force the execution of the Get-Date cmdlet. The –force parameter is used to create the folder that is expressed in the path, if the folder does not exist. This portion of the script is seen here inside a pair of curly brackets (also known as the script block):

  {
    New-Item -Path $path -ItemType file -Value $(Get-Date) -force
  }

If the file already exists, the string “File exists” is displayed on the Windows PowerShell console, and the script is exited. To exit a running Windows PowerShell script, you use the exit command. To combine two separate commands on the same line, you separate the commands with a semicolon. This part of the script is seen here:

Else

 { “File exists” ; exit }

When the script runs, the IwasHere.txt file is created in the C:\fso directory, as seen here:

Image of IwasHere.txt file created in C:\fso directory

 

The IwasHere.txt file contains the date and time the script was run. This can be seen here:

Image of date and time script was run

 

EC, this concludes looking at the DetermineIfFileExists.ps1 Windows PowerShell script. The Test-Path cmdlet can be extremely useful when attempting to determine if a file exists or not. The only trick to using it is realizing you do not need to directly evaluate the Boolean value that is returned by the cmdlet. Because there is also a registry provider inside Windows PowerShell, you can also use the Test-Path cmdlet to determine if a registry key exists or not. It is really cool and powerful stuff.

If you want to know exactly what we will be covering tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson and Craig Liebendorfer, Scripting Guys 

 

0 comments

Discussion is closed.

Feedback usabilla icon