{"id":54733,"date":"2008-12-29T11:42:00","date_gmt":"2008-12-29T11:42:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/12\/29\/hey-scripting-guy-how-can-i-delete-and-manage-pdf-files\/"},"modified":"2008-12-29T11:42:00","modified_gmt":"2008-12-29T11:42:00","slug":"hey-scripting-guy-how-can-i-delete-and-manage-pdf-files","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-delete-and-manage-pdf-files\/","title":{"rendered":"Hey, Scripting Guy! How Can I Delete and Manage PDF Files?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/H2>\n<P>Hey, Scripting Guy! We are implementing a document management system at work, and users are no longer allowed to store PDF files. I need to search a folder for the existence of PDF files. If the folder contains any PDF files, I want to delete them. If on the other hand there are no PDF files in the folder, I would like to create a file called <B>nopdf.txt<\/B>. This is because we will use <A href=\"http:\/\/www.microsoft.com\/systemcenter\/configurationmanager\/en\/us\/default.aspx\" target=\"_blank\">Systems Center Configuration manager<\/A> software inventory to inventory computers that have the <B>nopdf.txt<\/B> file.<BR><BR>&#8211; RU<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hi RU,<\/P>\n<P>That is a rather interesting idea. Back in the days when I used to work with Systems Management Server (SMS), I used to do a similar trick to allow me easily track the progress of various operations.<\/P>\n<P>For information about working with files and folders in Windows PowerShell see <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/pstips\/oct07\/pstip1005.mspx\" target=\"_blank\">this article<\/A>. You may also wish to see <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/msh\/cmdlets\/files.mspx\" target=\"_blank\">this section<\/A> of &#8220;What Can I Do with Windows PowerShell&#8221; that deals specifically with files and folders. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\" target=\"_blank\">Windows PowerShell scripting hub<\/A> is a good place to get started with Windows PowerShell, and it includes download links and other items of use. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/begin\/archive.mspx\" target=\"_blank\">Sesame Script archive<\/A> has several VBScript articles dealing with files and folders. They are worth a look for VBScript examples. The community script repository has a good selection of <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/csc\/scripts\/files\/default.mspx\" target=\"_blank\">files and folders scripts<\/A> in VBscript. You also may want to check the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/files.mspx\" target=\"_blank\">Hey, Scripting Guy! archive<\/A> for a number of VBScript examples of working with files and folders.<\/P>\n<P>Interestingly enough, with Windows PowerShell we have a short syntax that can be used from the command line. If we wanted to search a folder to see if there are any PDF files in it, and then print out a message if there were none, we could use this kind of syntax:<\/P><PRE class=\"codeSample\">if(!(gci C:\\fso *.pdf -R)) { &#8220;no pdf&#8221;}<\/PRE>\n<P>The problem with this type of syntax is that it is hard to read. This is the difference between working from the command line and writing a script. The above command begins by using an <B>if<\/B> statement. The <B>if<\/B> statement has the condition that is evaluated in smooth parentheses and the code that will be executed in curly brackets. In the <B>if<\/B> statement, we use the <B>Get-ChildItem<\/B> cmdlet (or \u201cgci\u201d) to look for PDF files in the <B>fso<\/B> directory. The <B>-r<\/B> means to recurse. The exclamation mark, <B>!<\/B>, is used as the <B>not<\/B> operator. This is similar syntax to when your friend comes up to you and says, &#8220;You are looking good today. Not.&#8221; In the same way, the <B>not<\/B> operator means if we do not find any PDF files in the <B>fso<\/B> directory, we will print out &#8220;no pdf&#8221;. Let&#8217;s see how we would use this in a script. The script we came up with is called <B>CheckForPdfAndCreateMarker.ps1<\/B>, and it is seen&nbsp;here.<\/P><PRE class=\"codeSample\">$path = &#8220;c:\\fso&#8221;\n$include = &#8220;*.pdf&#8221;\n$name = &#8220;nopdf.txt&#8221;\nif(!(Get-ChildItem -path $path -include $include -Recurse)) \n  { \n    &#8220;No pdf was found in $path. Creating $path\\$name marker file.&#8221;\n    New-Item -path $path -name $name -itemtype file -force |\n    out-null\n  } #end if not Get-Childitem\nELSE\n {\n  $response = Read-Host -prompt &#8220;PDF files were found. Do you wish to delete &lt;y&gt; \/&lt;n&gt;?&#8221;\n  if($response -eq &#8220;y&#8221;)\n    {\n     &#8220;Pdf files will be deleted.&#8221;\n     Get-ChildItem -path $path -include $include -recurse |\n      Remove-Item\n    } #end if response\n  ELSE\n   { \n    &#8220;PDF files will not be deleted.&#8221;\n   } #end else reponse\n } #end else not Get-Childitem\n<\/PRE>\n<P>In the script, the first thing we do is define three variables. The first variable holds the path to the folder we are going to search, and we name it <B>$path<\/B>. The second variable holds the files we will be searching for. Because this value gets supplied to the <B>-include<\/B> parameter, I called the variable <B>$include<\/B>. Lastly, we have the name of the text file we wish to create. I call it <B>$name<\/B>. This section of code is seen&nbsp;here:<\/P><PRE class=\"codeSample\">$path = &#8220;c:\\fso&#8221;\n$include = &#8220;*.pdf&#8221;\n$name = &#8220;nopdf.txt&#8221;\n<\/PRE>\n<P>As a best practice, when working with scripts I tend to make the variable name the same as the parameter name. This makes the code easy to read and easier to understand.<\/P>\n<P>Next we need to search for the PDF files. To do this, we use the <B>Get-ChildItem<\/B> cmdlet. This cmdlet is great at searching folders, and it returns either a <B>fileinfo<\/B> object or a <B>directoryinfo<\/B> object, depending on whether the item found is a file or a folder. Because we want to search the folder specified in the <B>-path<\/B> parameter and look for the filetypes (PDF) included in the <B>$include<\/B>, variable we need to use the <B>-recurse<\/B> parameter. We are only interested in the fact that the files either exist or don\u2019t exist. This is a Boolean condition. Just like a light switch is either on or off, something is true or false, exists or does not exist. These are all Boolean conditions. You could use an <B>if<\/B> statement like this in VBScript, but most people never did. While it might look a little strange at first, it is a nice construction. Note that the condition we are negating needs its own set of parentheses. Just like in high school algebra, things inside parentheses get operated upon before things outside the parentheses. Here is the line of code:<\/P><PRE class=\"codeSample\">if(!(Get-ChildItem -path $path -include $include -Recurse))<\/PRE>\n<P>In the code block for the <B>if<\/B> statement, we first print out a message that states no PDF file was found, and we are going to create the marker file. The cool thing here is the way the expanding strings work. An expanding string is a double quotation mark. The advantage of an expanding string is that it will expand the value of a variable when it is placed in the quotation marks. Single quotation marks are literal quotation marks. What is placed inside them is what is printed out. Here are some examples of&nbsp;this:<\/P><PRE class=\"codeSample\">PS C:\\&gt; $a = &#8220;string&#8221;\nPS C:\\&gt; &#8220;$a is a string&#8221;\nstring is a string\nPS C:\\&gt; &#8216;$a is a string&#8217;\n$a is a string\nPS C:\\&gt;\n<\/PRE>\n<P>In our code block, after we have printed out a message, we then create the empty file in our folder. To do this we use the <B>New-Item<\/B> cmdlet. <B>New-Item<\/B> can be used to create files, folders, and other things as well. This is why it is called <B>New-Item<\/B> instead of <B>New-File<\/B>. To create a file, we use the <B>-itemtype<\/B> of <B>file<\/B>. To create a folder we use the <B>-itemtype<\/B> of <B>directory<\/B>. It is possible the file already exists in the directory. To handle this eventuality, we use the <B>-force<\/B> parameter, which will cause the command to overwrite the existing file. We do not want to clutter the screen with confirmation messages, so we pipe the returned information to the <B>out-null<\/B> cmdlet. This code is seen&nbsp;here: <\/P><PRE class=\"codeSample\">{ \n    &#8220;No pdf was found in $path. Creating $path\\$name marker file.&#8221;\n    New-Item -path $path -name $name -itemtype file -force |\n    out-null\n  } #end if not Get-Childitem\n<\/PRE>\n<P>When no PDF files are found, we see this message:<\/P><IMG height=\"248\" alt=\"The message shown when no PDF files are found\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1229\/hsg_ff1_01.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>In the <B>else<\/B> clause, we need to handle the situation in which there are PDF files in the folder. We could just go ahead and delete the things, and then comment out the <B>Read-Host<\/B> line and the <B>if<\/B> and <B>else <\/B>clause. But this also gives me a chance to show you how to use <B>read-host<\/B> to solicit input from the user. The <B>Read-Host<\/B> cmdlet displays a prompt. If you want to capture the user response, use a variable to hold the results of the cmdlet. In this example, I use the variable <B>$response<\/B> to hold the user response. This section of the script is seen&nbsp;here:<\/P><PRE class=\"codeSample\">ELSE\n {\n  $response = Read-Host -prompt &#8220;PDF files were found. Do you wish to delete &lt;y&gt; \/&lt;n&gt;?&#8221;\n<\/PRE>\n<P>Do not use <B>$input<\/B> for the input to the <B>read-host<\/B> cmdlet, as <B>$input<\/B> is an automatically created variable that is used for other things in Windows PowerShell. It will cause strange things to happen if you use this variable for your own purposes.<\/P>\n<P>When we run the script and PDF files are found, we are greeted with this message:<\/P><IMG height=\"248\" alt=\"The message shown when PDF files are found\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1229\/hsg_ff1_02.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>We need to evaluate the response. To do this we use the <B>if<\/B> statement. In Windows PowerShell, we do not use the equals sign (<B>=<\/B>) for the equality operator. Instead, we use <B>-eq<\/B>, <B>-ieq<\/B>, and <B>-ceq<\/B> for equality. The first one is case insensitive, the second is likewise case insensitive, and the last one is the case sensitive equality operator. If the value of <B>$response<\/B> is equal to &#8220;y&#8221;, we print out a message that states the PDF files will be deleted, and we once again use the <B>Get-ChildItem<\/B> cmdlet to provide a collection of all the PDF files in the folder. The cool thing is we pipeline the resulting information to the <B>Remove-Item<\/B> cmdlet, which deletes the files. This is seen&nbsp;here:<\/P><PRE class=\"codeSample\">if($response -eq &#8220;y&#8221;)\n    {\n     &#8220;Pdf files will be deleted.&#8221;\n     Get-ChildItem -path $path -include $include -recurse |\n      Remove-Item\n    } #end if response\n<\/PRE>\n<P>When the user types &#8220;y&#8221;, the screen changes as seen here:<\/P><IMG height=\"248\" alt=\"The screen changes when the user types 'y'\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1229\/hsg_ff1_03.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>But if the value of <B>$response<\/B> was anything other than &#8220;y&#8221;, we print out a message that the files will not be deleted and we exit the script. This is seen&nbsp;here:<\/P><PRE class=\"codeSample\">ELSE\n   { \n    &#8220;PDF files will not be deleted.&#8221;\n   } #end else reponse\n } #end else not Get-Childitem\n<\/PRE>\n<P>RU, hope U R satisfied with this script. Get it? Script you again soon.<\/P>\n<P><FONT class=\"Apple-style-span\" face=\"Verdana\" size=\"3\"><SPAN class=\"Apple-style-span\"><B><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/B><\/SPAN><\/FONT><\/P><FONT class=\"Apple-style-span\" face=\"Verdana\" size=\"3\"><B><\/B><\/FONT><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! We are implementing a document management system at work, and users are no longer allowed to store PDF files. I need to search a folder for the existence of PDF files. If the folder contains any PDF files, I want to delete them. If on the other hand there are no PDF [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[38,3,12,45],"class_list":["post-54733","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-files","tag-scripting-guy","tag-storage","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! We are implementing a document management system at work, and users are no longer allowed to store PDF files. I need to search a folder for the existence of PDF files. If the folder contains any PDF files, I want to delete them. If on the other hand there are no PDF [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54733","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54733"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54733\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54733"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54733"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54733"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}