Я пытаюсь написать сценарий для удаления символов из имен файлов в определенной папке с помощью PowerShell. Он предлагает пользователю ввести, сколько символов он хочет удалить спереди и сзади, а также определенную строку, которую он хочет удалить.

# Prompt User how many characters in the front they want removed
$FrontRemove = Read-Host 'Enter how many characters you want removed from the front'

# Prompt user how many characters in the back they want removed
$BackRemove = Read-Host 'Enter how many characters you want removed from the back'

# Prompt user for string to be removed
$MiddleRemove = Read-Host 'Enter a string you want removed from the file name'

dir | Rename-Item -NewName{$_.name.substring(0,$_.BaseName.length-$BackRemove)}
dir | Rename-Item -NewName{$_.name.substring($FrontRemove)}
dir | Rename-Item -NewName{$_.name -replace "$MiddleRemove", ""}

Текущая проблема, с которой я столкнулся, заключается в том, что он удаляет расширения этих файлов, а также переименовывает сам скрипт. Как мне сохранить расширения файлов и исключить .ps1?

1
Higgm57 5 Окт 2018 в 17:58

1 ответ

Лучший ответ

Есть несколько вещей, которые я бы изменил в вашем коде. Во-первых, вы вызываете dir (Get-ChildItem) для каждого изменения имен файлов, если это можно сделать за один вызов.

Кроме того, в нем отсутствует какая-либо форма проверки, можно ли сделать то, что ввел пользователь, для каждого файла, возвращаемого Get-ChildItem.

Get-ChildItem без указания пути будет искать элементы в текущем местоположении . Если это не то, что вы хотите, возможно, безопаснее установить путь, как в приведенном ниже коде.

$folder = '<ENTER THE PATH TO THE FOLDER WHERE THE FILES TO RENAME ARE HERE>'

# Prompt User how many characters in the front they want removed --> number
[int]$FrontRemove = Read-Host 'Enter how many characters you want removed from the front'

# Prompt user how many characters in the back they want removed --> number
[int]$BackRemove = Read-Host 'Enter how many characters you want removed from the back'

# Prompt user for string to be removed --> string
[string]$MiddleRemove = Read-Host 'Enter a string you want removed from the file name'

# Since we are using the -replace function, which is using Regular Expression replacement,
# we need to make sure all 'special' characters in the string are escaped.
if (![string]::IsNullOrEmpty($MiddleRemove)) {
    $MiddleRemove = [Regex]::Escape($MiddleRemove)
}

Get-ChildItem -Path $folder -File | Where-Object {$_.Name -notlike '*.ps1'} |
    ForEach-Object {
        $directory = $_.DirectoryName     # or [System.IO.Path]::GetDirectoryName($_.FullName)  or use Split-Path $_.FullName -Parent
        $filename  = $_.BaseName          # or [System.IO.Path]::GetFileNameWithoutExtension($_.Name)
        $extension = $_.Extension         # or [System.IO.Path]::GetExtension($_.Name)

        # test user input and remove/replace only if possible
        if ($FrontRemove -gt 0 -and $FrontRemove -lt $filename.Length) {
            $filename = $filename.Substring($FrontRemove)
        }
        if ($BackRemove -gt 0 -and $BackRemove -lt $filename.Length) {
            $filename = $filename.Substring(0, $filename.Length - $BackRemove)
        }
        if (![string]::IsNullOrEmpty($MiddleRemove)) {
            $filename = $filename -replace $MiddleRemove, ''
        }

        # now see if we still have a name left and if indeed the filename has changed
        if (![string]::IsNullOrEmpty($filename) -and $filename -ne $_.BaseName) {
            # re-append the extension of the file
            if (![string]::IsNullOrEmpty($extension)) { $filename += $extension }
            # join it with the directory to become a complete path and filename
            $newname = Join-Path -Path $directory -ChildPath $filename
            Rename-Item -LiteralPath $_.FullName -NewName $newname -Force
        }
        else {
            Write-Warning "The options you entered would remove the entire filename. Action skipped on '$($_.FullName)'"
        }
    }
2
halfer 15 Окт 2018 в 17:37