{"id":53903,"date":"2009-04-23T23:16:00","date_gmt":"2009-04-23T23:16:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/04\/23\/hey-scripting-guy-how-can-i-work-with-directories-files-and-folders-by-using-windows-powershell\/"},"modified":"2009-04-23T23:16:00","modified_gmt":"2009-04-23T23:16:00","slug":"hey-scripting-guy-how-can-i-work-with-directories-files-and-folders-by-using-windows-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-work-with-directories-files-and-folders-by-using-windows-powershell\/","title":{"rendered":"Hey, Scripting Guy! How Can I Work with Directories, Files, and Folders by Using Windows PowerShell?"},"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! This may not sound too exciting, but I do a lot of work with files and folders. I constantly have to create folders and files, move files, and move folders. This was easy to do by using VBScript, but nevertheless it always required at least six lines of code to do anything. Is it possible to simplify this process by using Windows PowerShell? <BR><BR>&#8211; RH<\/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 RH,<\/P>\n<P>I can definitely identify with your desire to simplify things. It is always interesting on a dive boat for example to look at one\u2019s fellow divers. I remember one time while diving off the coast of Maui, Hawaii, in the United States. It was a clear calm day. The water was like glass, and there was not a cloud in the sky. We were doing a shallow dive, less than 40 feet (12 meters) deep. As I was looking around, I saw one guy completely decked out. He had a <A href=\"http:\/\/en.wikipedia.org\/wiki\/Safety_sausage\" target=\"_blank\">safety sausage<\/A>, a signal mirror, a spare air bottle, a spare mask, two flashlights, two slates, two knives, a navigating board, and a camera. Although I am all about safety when diving, this dude was geared up for a night time, drift, wreck dive (an activity that really does not exist). I on the other hand simply took my camera, and I came back with the picture seen just below. My friend on the dive boat came back complaining about the lack of sea life at the site. Perhaps he lost sight of the sea turtles while fussing around with all the gear.<\/P><IMG height=\"375\" alt=\"Image of a sea turtle off Maui, Hawaii\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0423\/hsg-04-23-09-01.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>One of the exciting benefits of using Windows PowerShell and learning how to use the built-in cmdlets is that it frees us from worrying about all the details. We know Windows PowerShell is built upon the .NET Framework. But we often do not have to worry about the .NET Framework classes that are being used. If we are interested in working with files and folders, there are cmdlets we can use to provide this functionality.<\/P>\n<TABLE class=\"dataTable\" id=\"EBD\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\">This week we are looking at the basics of Windows PowerShell. Windows PowerShell is installed by default on Windows 7 and Windows Server 2008 R2. It is an optional installation on Windows Server 2008 and a download for <A href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?displaylang=en&amp;FamilyID=c6ef4735-c7de-46a2-997a-ea58fdfcba63\">Windows Vista<\/A>, <A href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?displaylang=en&amp;FamilyID=6ccb7e0d-8f1d-4b97-a397-47bcc8ba3806\">Windows XP<\/A>, and <A href=\"http:\/\/www.microsoft.com\/downloads\/details.aspx?displaylang=en&amp;FamilyID=10ee29af-7c3a-4057-8367-c9c1dab6e2bf\">Windows Server 2003<\/A>. The <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\">Windows PowerShell Scripting Hub<\/A> is a good place to get started with Windows PowerShell.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>If we want to produce a listing of all the folders and the dates on which those folders were modified, we can use the <B>FileSystemObject<\/B> in VBScript and produce a script that is similar to the <B>ListFoldersAndModifiedDates.vbs<\/B> script. Interestingly enough, RH, it is exactly six lines of code long. You will notice we first create an instance of the <B>FileSystemObject<\/B> and store it in the <B>objFSO<\/B> variable. We then return a folder object by using the <B>GetFolder<\/B> method to connect to the root of the C drive. Next, we return a folder collection by calling the <B>SubFolders<\/B> method. We then walk through the collection by using the <B>For\u2026Each\u2026Next<\/B> statement. We then use a trick I came up with several years ago to display both the name of the folder and the date the folder was changed. The trick is to include both properties on the same line as the <B>Wscript.Echo<\/B> command. The <B>ListFoldersAndModifiedDates.vbs<\/B> script is seen&nbsp;here:<\/P><PRE class=\"codeSample\">Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)\nSet objFolder = objFSO.GetFolder(&#8220;C:\\&#8221;)\nSet colFOlders = objFolder.SubFolders\nFor Each subFolder In colFOlders\n  WScript.Echo subFolder.Name, subFolder.DateLastModified\nNext\n<\/PRE>\n<P>In Windows PowerShell we can get a collection of files and folders by using the <B>Get-ChildItem<\/B> cmdlet. When we use the <B>Get-ChildItem<\/B> cmdlet without supplying any values for the parameters, it returns a list of all the files and folders in the root directory:<\/P><IMG height=\"248\" alt=\"Image of a list of all files and folders returned by the Get-ChildItem cmdlet\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0423\/hsg-04-23-09-02.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>To return a listing of only directories, you have to determine a way to separate the directories from the files that are returned by the default use of the <B>Get-ChildItem<\/B> cmdlet. There are actually several ways to do this, but they all involve pipelining the results of the <B>Get-ChildItem<\/B> cmdlet to the <B>Where-Object<\/B> cmdlet. Most of the time you can examine the column headings in the display results to find a property that you can use with the <B>Where-Object<\/B> cmdlet to create a filter for your command. The default column headings used with the <B>Get-ChildItem<\/B> cmdlet are listed here: <B>Mode<\/B>, <B>LastWriteTime<\/B>, <B>Length<\/B>, and <B>Name<\/B>. Of the four, the <B>Mode<\/B> column will be of the most use because it has a &#8220;d&#8221; in the first position if the item is a directory. You use the <B>Get-ChildItem<\/B> cmdlet to retrieve the file and folder objects from the root drive. Then you pipeline the objects to the <B>Where-Object<\/B> cmdlet. Inside the script-block for the <B>Where-Object<\/B> cmdlet, you use the <B>$_<\/B> automatic variable to examine each object as it comes across the pipeline. The property that you are interested in is the <B>mode<\/B> property. You use the <B>\u2013like<\/B> operator to perform a wildcard match of any value that begins with the letter &#8220;d&#8221; and is followed by any other value. The command to list directories off the root drive is seen here:<\/P><PRE class=\"codeSample\">PS C:\\&gt; Get-ChildItem | Where-Object { $_.mode -like &#8216;d*&#8217; }<\/PRE>\n<P>The results of the <B>list directory<\/B> command are seen here:<\/P><IMG height=\"230\" alt=\"Image of the results of the list directory command\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0423\/hsg-04-23-09-03.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>If you want to exactly replicate the output from the <B>ListFoldersAndModifiedDates.vbs<\/B> script, you have to pass the results further down the pipeline so that you can reduce the information that is returned. There are two methods that you can use to reduce the information. The first method is to use the <B>Select-Object<\/B> cmdlet to choose only the <B>Name<\/B> and the <B>LastWriteTime<\/B> properties. When you use the <B>Select-Object<\/B> cmdlet to select certain properties, the object that is returned is a custom object that contains only the properties that you select and the methods that are common to all Windows PowerShell objects. The members of the newly created custom object are shown&nbsp;:<\/P><PRE class=\"codeSample\">   TypeName: System.Management.Automation.PSCustomObject<\/p>\n<p>Name          MemberType   Definition\n&#8212;-          &#8212;&#8212;&#8212;-   &#8212;&#8212;&#8212;-\nEquals        Method       System.Boolean Equals(Object obj)\nGetHashCode   Method       System.Int32 GetHashCode()\nGetType       Method       System.Type GetType()\nToString      Method       System.String ToString()\nLastWriteTime NoteProperty System.DateTime LastWriteTime=8\/17\/2008 1:23:10 PM\nName          NoteProperty System.String Name=19287a2cfb60a3bbcca7\n<\/PRE>\n<P>It is important to understand the object that is returned by the query so that you can perform additional processing on the object, if you want to do so. The <B>Get-ChildItem<\/B> command that lists the name and last write time of all the directories off the root drive is shown here. This command is a single command that is broken at the pipeline character for readability:<\/P><PRE class=\"codeSample\">PS C:\\&gt; Get-ChildItem | Where-Object { $_.mode -like &#8216;d*&#8217; } | \nSelect-Object -Property Name, LastWriteTime\n<\/PRE>\n<P>The <B>Get-ChildItem<\/B> command are shown here:<\/P><IMG height=\"203\" alt=\"Image of the results of the Get-ChildItem command\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0423\/hsg-04-23-09-04.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>You can reduce the typing without sacrificing any of the readability of the command by using <B>dir<\/B> as the alias for <B>Get-ChildItem<\/B>, <B>where<\/B> as the alias for <B>Where-Object<\/B>, and <B>select<\/B> as the alias for <B>Select-Object<\/B>. You can also omit the <B>\u2013property<\/B> parameter because it is the default parameter for the <B>Select-Object<\/B> cmdlet. The revised command is shown here:<\/P><PRE class=\"codeSample\">PS C:\\&gt; dir | where { $_.mode -like &#8216;d*&#8217;} | select name, lastwritetime<\/PRE>\n<P>Another way to produce a listing of the name and the last write time of each directory in the root directory is to send the output to the <B>Format-Table<\/B> cmdlet, as illustrated&nbsp;here:<\/P><PRE class=\"codeSample\">PS C:\\&gt; Get-ChildItem | Where-Object { $_.mode -like &#8216;d*&#8217; } | Format-Table -Prop\nerty Name, LastWriteTime\n<\/PRE>\n<P>The output produced by using the <B>Format-Table<\/B> cmdlet is almost the same as the output produced by using the <B>Select-Object<\/B> cmdlet:<\/P><IMG height=\"203\" alt=\"Image of the output produced by using the Format-Table cmdlet\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0423\/hsg-04-23-09-05.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>The problem with using <B>Format-Table<\/B> to format your output is that if you have to do anything else to the data, you are left with a series of five different format objects that are basically useless for additional data manipulation. Depending on what you are trying to achieve, even the custom <B>Windows PowerShell<\/B> object that is created by the <B>Select-Object<\/B> cmdlet will cause you problems. As a best practice you should always perform all data manipulation before sending your object to an output cmdlet. <\/P>\n<P>At this point, in your pipeline you have one last thing that you can easily do: You can send the output to a text file. The easiest way to do this is to use the <B>&gt;&gt;<\/B> redirection operator as shown here (once again we have broken the single command at the pipeline character for readability):<\/P><PRE class=\"codeSample\">PS C:\\&gt; Get-ChildItem | Where-Object { $_.mode -like &#8216;d*&#8217; } | \nFormat-Table -Property Name, LastWriteTime &gt;&gt; c:\\fso\\directoryFile.txt\n<\/PRE>\n<P>The text file that is produced by the redirection operator maintains the format that is displayed on the console:<\/P><IMG height=\"230\" alt=\"Image of the text file that is produced by the redirection operator\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/april\/hey0423\/hsg-04-23-09-06.jpg\" width=\"500\" border=\"0\"> \n<P>&nbsp;<\/P>\n<P>Today, we have looked at using Windows PowerShell to simplify working with directories, folders, and files. With the redirection operator, it is easy to write the results of the command to a text file. I hope that you have enjoyed this look at the basics of Windows PowerShell this week. Join us tomorrow for Quick-Hits Friday as we open up the mailbag and see how many questions we can answer in just a few sentences. Until tomorrow, keep cool.<\/P>\n<P>&nbsp;<\/P>\n<P><B>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/B><\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! This may not sound too exciting, but I do a lot of work with files and folders. I constantly have to create folders and files, move files, and move folders. This was easy to do by using VBScript, but nevertheless it always required at least six lines of code to do anything. [&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,11,51,3,4,12,45],"class_list":["post-53903","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-files","tag-folders","tag-getting-started","tag-scripting-guy","tag-scripting-techniques","tag-storage","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! This may not sound too exciting, but I do a lot of work with files and folders. I constantly have to create folders and files, move files, and move folders. This was easy to do by using VBScript, but nevertheless it always required at least six lines of code to do anything. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53903","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=53903"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/53903\/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=53903"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=53903"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=53903"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}