To solve an issue at work with some zip files in a folder, I needed to create new folders based on the .zip file names, then, once the new folders had been created, copy the .zip file to the newly named folder.
foreach($zip in ( Get-ChildItem 'C:\zipfiles' | Where {(-not $_.PSIsContainer) -and (-not $_.PSIsContainer)})) {
New-Item -Path (Split-Path $zip.fullname) -Name (Split-Path $zip.fullname -Leaf).ToString().Replace(".zip","") -ItemType Directory
Copy-Item -Path $zip.fullname -Destination "$(Split-Path $zip.fullname)\$((Split-Path $zip.fullname -Leaf).ToString().Replace('.zip',''))"
}
Above is the script I used to accomplish this. Below is the breakdown of how it works. First, start by gathering a collection of zip file names. The command,
Get-ChildItem 'C:\zipfiles' | Where {(-not $_.PSIsContainer) -and (-not $_.PSIsContainer)}
excludes folders, and, returns only .zip files. The Foreach-Object loop iterates the collection into a variable named $zip. Once the loop starts going over the collection it creates a New-Item, in this case, a Directory, with this command.
New-Item -Path (Split-Path $zip.fullname) -Name (Split-Path $zip.fullname -Leaf).ToString().Replace(".zip","") -ItemType Directory
This command has several parts:
- New-Item: creates a new item
- -Path: specifies the path to the new object
- (Split-Path $zip.fullname): returns the file path the file in the current iteration. In this case, we want the folderpath, not the file name
- -Name: Specifies the name of the folder to create
- (Split-Path $zip.fullname -Leaf).ToString().Replace(".zip",""): returns to the -Leaf (file name) of the $zip file currently being processed. It then converts the object to a string object, and, replaces .zip with nothing.
- -ItemType: Directory specifies the object type to create. In this case, a folder
The second line of the command copies the zip file to the newly named folder,
Copy-Item -Path $zip.fullname -Destination "$(Split-Path $zip.fullname)\$((Split-Path $zip.fullname -Leaf).ToString().Replace('.zip',''))"
and has a similar number of parts:
- Copy-Item: copies the item specified by the parameters
- -Path: the path to the source object
- $zip.fullname: the full path the current object
- -Destination: the place the object is being copied to
- "$(Split-Path $zip.fullname)\$((Split-Path $zip.fullname -Leaf).ToString().Replace('.zip',''))": this has several parts, so, I'll break them down, one by one:
- double quotes: forces the contents to be evaluated. If I had used single quotes, it would be a literal. By using double quotes, Powershell parses the string looking for special characters.
- $(Split-Path $zip.fullname): This notation forces the contents, Split-Path $zip.fullname to be evaluated. In this case, we want it to execute to return the path portion of the object $zip.fullname. The way to do this here is $().
- As above, Split-Path $zip.fullname returns the path to the current object
- \: this simply acts as a way to join the folder path and the file name. Another way to do thing would be to do Join-Path -Path -ChildPath. The \ is automatically inferred between the two objects.
- $((Split-Path $zip.fullname -Lead).ToString().Replace('.zip','')): There are, again, several parts. I'll break them down as well.
- The $(), again, represents a forced evaulation.
- The first part, (Split-Path $zip.fullname -Leaf), similar to what is shown above, returns the file name when you specify the -Leaf switch.
- .ToString() allows the .System.String.Replace() method to be called. Otherwise, I would get an error by trying to access a .Replace() method on a File object which does not exist.
- .Replace('.zip',''): this causes the file extension, .zip, to be replaced with nothing. If we didn't do this, we'd have folders named after .zip files, instead of, as we want, the folder names to match the file names.
As I indicated earlier, there's a lot packed into this little script. But, it allows a lot to get done with very little work.
0 comments:
Post a Comment