1

I have some files like

The Fast and the Furious Tokyo Drift   .avi
The Fast and the Furious 1080p  .mkv

I want to rename these filenames in this way

The Fast and the Furious Tokyo Drift.avi
The Fast and the Furious.mkv

But powershell script fails to do this task

I try to run this code

# Specifies the directory containing the files to be renamed
$directory = 'C:\temp\film\test2'

# Ottieni l'elenco dei file nella directory con le estensioni specificate
$files = Get-ChildItem $directory -Include '*.avi', '*.mkv', '*.mp4'

# Initializes a counter for files of the same name
$counter = 1

# Cycle through each file
foreach ($file in $files) {
    # Create a search string that locates all occurrences of the words to be deleted,
    # regardless of the case
    $search = '(?i)\b(ITA|ENG|AC3|BDRip|1080p|X265_ZMachine)\b|\b1080p\b'
    
    # Replace all occurrences of the words to be deleted with an empty string
    $newName = $file.Name -replace $search, ''
    
    # Eliminate double spaces
    $newName = $newName -replace '  ', ' '
    
    # Remove the spaces at the beginning and end of the file name
    # Create the new file name
    $newName = "$($newName.TrimEnd())$($file.Extension)"
    
    # Check if the new filename is already in the directory
    while (Test-Path -Path "$directory\$newName") {
        # If the new file name already exists, add a sequential number to the name
        $newName = "$($file.BaseName)_$counter$($file.Extension)"
        $counter++
    }
    
    # Rename the file to the new name
    Rename-Item -Path $file.FullName -NewName $newName
    
    # Reset the counter for files with the same name
    $counter = 1
}

In summary, the logic of the code is this

  1. Specifies the directory containing the files to be renamed.
  2. Gets the list of files in the directory with the specified extensions using the Get-ChildItem command with the -Include parameter.
  3. Initializes a counter for files of the same name.
  4. Loop through each file in the resulting list.
  5. Create a search string that finds all occurrences of the words to delete, regardless of case.
  6. Replaces all occurrences of the words to be deleted with an empty string.
  7. Eliminate double spaces.
  8. Remove the spaces at the beginning and end of the file name.
  9. Create the new file name.
  10. Check if the new filename is already in the directory. If the new name already exists, add a sequential number to the name.
  11. Rename the file to the new name using the Rename-Item command.
  12. Reset the counter for files with the same name.
user3520363
  • 360
  • 1
  • 15
  • 1
    `$file.Name` includes the filename extension; try operating on `$file.BaseName` – mklement0 Dec 28 '22 at 00:16
  • I change `$newName = "$($newName.TrimEnd())$($file.Extension)"` into `$newName = "$($newName.TrimEnd())$($file.BaseName)"` but nothing happens – user3520363 Dec 28 '22 at 00:48
  • If I edit this string `$files = Get-ChildItem $directory -Include '*.avi', '*.mkv', '*.mp4'` into `$files = Get-ChildItem $directory` it renames but also renames all files adding (1) after extension. Why this happens ? In the same folder I have rename.ps1 and with this code edit `$files = Get-ChildItem $directory` I get rename.ps1 (1) – user3520363 Dec 28 '22 at 00:54
  • 1
    You're using `-Include` which is bugged. It requires the use of `\*` after the path, or `-Recurse`. So, it should be `$directory = 'C:\temp\film\test2\*'`. – Abraham Zinala Dec 28 '22 at 00:55
  • If I use `$files = Get-ChildItem $directory -Recurse -Filter '*.avi', '*.mkv', '*.mp4'` it returns me this error: **Cannot convert 'System.Object[]' to the type 'System.String' required by | parameter 'Filter'. Specified method is not supported.** – user3520363 Dec 28 '22 at 01:02
  • 1
    Filter only supports one item. – Doug Maurer Dec 28 '22 at 01:04
  • ok, this should be fixed code https://pastebin.com/raw/MxdANPTy but final space before .avi extension is not removed, any idea ? – user3520363 Dec 28 '22 at 01:39

1 Answers1

2

Summarizing the helpful comments:

$files = Get-ChildItem $directory -Include '*.avi', '*.mkv', '*.mp4'

should be either (note the trailing \*, which is needed due to -Include's counterintuitive behavior - see this answer):

# Only match files of interest located directly in $directory
$files = Get-ChildItem $directory\* -Include *.avi, *.mkv, *.mp4

or (no \* needed, because -Recurse is used):

# Match files of interest located in $directory and any of it subdirs.
$files = Get-ChildItem -Recurse $directory -Include *.avi, *.mkv, *.mp4

$newName = $file.Name -replace $search, ''

should be (.BaseName instead of .Name):

$newName = $file.BaseName -replace $search, ''
mklement0
  • 382,024
  • 64
  • 607
  • 775