Beginner: Script to rename files based on other filenames or text file list

Hi Everyone,

I’m a beginner in Powershell and am trying to construct scripts to assist with learning. I’ve been using the Microsoft Powershell site which has been a great help with learning cmdlets, but I’m now at the stage where I’m trying to combine commands in order to achieve multiple actions in a script (still veerrrryy basic stuff :-).

I have the following:

  1. A folder called Pics, containing .jpg files
  2. A folder called Archives, containing .zip files
  3. A .txt file containing the filenames of the Archives directory, with ".zip" removed
I am trying to achieve either of the following, but mainly point 1:
  1. Rename all items in the Pics folder using the list contained in the .txt file
  2. Rename all items in the Pics folder using the filenames in the Archive folder, removing ".zip" in the process
This is assuming the files in the pics folder are already named so they appear in the same order as the contents of the Archive folder, and filename list in the .txt file.

I’ve not been able to find a working combination of Get-Content, Get-ChildItem and Rename-Item (possibly by losing the original value of $_ when piping into another command?) so wondering if I would need to achieve this using variables and loops or is there a way it can be achieved using basic cmdlets?

It would be better if you would post what you’ve tried and what is not working. First hint, you don’t need a text file. There is a property BaseName that that has the base file name with no extension, so you can just use Archive file collection:

PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Scripts\Archive\file1.zip
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\Scripts\Archive
PSChildName : file1.zip
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
Mode : -a----
VersionInfo : File: C:\Scripts\Archive\file1.zip
InternalName:
OriginalFilename:
FileVersion:
FileDescription:
Product:
ProductVersion:
Debug: False
Patched: False
PreRelease: False
PrivateBuild: False
SpecialBuild: False
Language:

BaseName : file1
Target : {}
LinkType :
Name : file1.zip
Length : 896
DirectoryName : C:\Scripts\Archive
Directory : C:\Scripts\Archive
IsReadOnly : False
Exists : True
FullName : C:\Scripts\Archive\file1.zip
Extension : .zip
CreationTime : 12/13/2018 5:15:50 PM
CreationTimeUtc : 12/13/2018 10:15:50 PM
LastAccessTime : 12/13/2018 5:15:50 PM
LastAccessTimeUtc : 12/13/2018 10:15:50 PM
LastWriteTime : 8/23/2018 10:02:57 AM
LastWriteTimeUtc : 8/23/2018 2:02:57 PM
Attributes : Archive

Next, there are a lot of logic errors you are going to deal with as there are a lot of assumptions.

  • What if there are there more files in Pic than there are in Archive or vice versa?
  • What if there are no files in Pic or Archive?
  • What if the order is based on datetime created and doesn't match?

If you want to do it simply learn, it can be done, but assuming what is in the directories would quickly break things in a production script. Please share what you’ve tried.

V3 introduced the PipelineVariable that can help when nesting…

'bits','abc','dhcp' |
    ForEach-Object { $_ } -PipelineVariable name |
        Get-Service -PipelineVariable service -ErrorAction SilentlyContinue |
            & { process{ "The service $name is present" }}

name comes directly from the string array.

Note: The name can be extracted from the object returned from get-service, but it shows the technique.