O Powershell pode ser usado para renomear arquivos com caminhos com mais de 260 caracteres?

4

Tenho centenas de arquivos com caminhos com mais de 260 caracteres que desejo renomear. Usando o Powershell, posso encontrar os nomes longos usando cmd /c dir /s /b |? {$_.length -gt 260} , mas os cmdlets reais não suportam nomes extensos de arquivos: Get-Item retornaria

"cannot find path [long path] because it does not exist"

Eu li que um módulo chamado NTFSSecurity pode trabalhar com caminhos longos, mas até agora só sei que ele pode listar os arquivos usando um cmdlet chamado Get-ChildItem2. Eu ainda não sei como renomear os arquivos dessa maneira.

Fora do Powershell, encontrei uma ferramenta chamada TLPD que pode listar os arquivos, mas isso é tudo.

Até agora eu só consegui lidar com isso manualmente renomeando as pastas pai para que o caminho se tornasse curto o suficiente para ser acessado (eu posso ser capaz de emular esse processo usando Powershell - mas eu apreciaria um maneira mais fácil)

Editar: para esclarecer, gostaria de manter os arquivos em vez de excluí-los o máximo possível.

    
por user 13.12.2016 / 03:10

4 respostas

1

Eu escrevi um script que funcionou. Obrigado ao jftuga pela sugestão do subst.

# This script searches through the search_path, finds file paths that are longer than total_path_length_threshold, and truncates the filename

### user settings ###

$test_run = $true                   # set to $false to start renaming for real
$search_path = "C:\my_folder\"      # the path to search for long names
$total_path_length_threshold = 260  # the length threshold to test
$characters_to_truncate = 5         # the number of characters to strip from the end of long filenames (a new identifier will also be added)
$log_file_path = "c:\my_folder\long_filename_log.txt"  # log file location

$virtual_drive = "v:"               # used for temporary processing using subst. Must look like "v:" and not like "v:\"

### end of user settings ###

Out-File $log_file_path
"Test run = $test_run" | Tee-Object $log_file_path -Append
"search_path = $search_path " | Tee-Object $log_file_path -Append
"total_path_length_threshold = $total_path_length_threshold " | Tee-Object $log_file_path -Append
"characters_to_truncate = $characters_to_truncate " | Tee-Object $log_file_path -Append

$counter = 0  # counter for creating new unique filenames
$collection = cmd /c dir $search_path /s /b |? {$_.length -gt $total_path_length_threshold }
$count_paths = ($collection | measure).count - 1

foreach ($path in $collection) {
    echo "found long path: $path"

    # get the parent's path
    $parent_path = Split-path -path $path

    # mount the parent to a virtual drive
    subst $virtual_drive $parent_path

    # get leaf element
    $leaf = split-path -leaf $path

    # make new short path
    $short_virtual_path = join-path $virtual_drive $leaf

    # get the long-name item 
    $item = Get-Item -LiteralPath $short_virtual_path

    if ($item -is [System.IO.fileinfo]) {
        # log long filename path
        "item $counter : Long filename path: $path" | Out-File $log_file_path -Append

        $filename = $item.name  #get the full filename

        # get filename extension
        $filename_extension = $item.Extension

        # get filename without extension:
        $basename = $item.BaseName    
        $basename_length = $basename.length 

        # give the new filename a unique index, to avoid duplicate filenames
        $new_index = "X" + $counter + "X"
        # the actual number of characters to cut is characters_to_truncate + new_index length
        $adjusted_characters_to_truncate = $characters_to_truncate + $new_index.length 

        if ( $basename_length -gt $adjusted_characters_to_truncate ) {
            $length_to_use = $basename_length - $adjusted_characters_to_truncate

            # shorten the filename by truncating it by specified num of char
            $new_filename = $basename.substring(0, $length_to_use ) + $new_index + $filename_extension

            # log the new filename path
            $new_path = $parent_path + $new_filename
            "item $counter : new filename path: $new_path " | Out-File $log_file_path -Append

            if (!$test_run) {
                # rename the file

                Rename-Item -LiteralPath $short_virtual_path $new_filename
            }

        }

    }

    $counter = $counter + 1

    #unmount the virtual drive
    subst v: /d
}

"Found $count_paths paths." | echo 
    
por 14.12.2016 / 15:24
0

existem este utilitário de nó legal que fará o trabalho chamado rimraf .Se você já tem o nó instalado, basta instalá-lo via npm

npm install -g rimraf
Uso: rimraf dir

Além disso, você pode usar o robocopof, que é capaz de criar caminhos maiores que o limite de 260 caracteres e também pode excluí-los

veja Página de Robocopy

Instale-o em Página da Microsoft

    
por 13.12.2016 / 06:48
0

Para excluir os caminhos usando o robocopy, você pode usar o parâmetro /purge em um diretório vazio.

Exemplo de CMD: Robocopy.exe C:\temp\SourceDir C:\Temp\EmptyDir /Purge

Aqui, o SourceDir é o diretório a ser excluído

Isso pode ser emparelhado com o PowerShell com bastante facilidade

Exemplo do PowerShell:

$Paths = Get-Content C:\Temp\DeleteDirectories
ForEach($Path in $Paths){
   Robocopy.exe $Path C:\Temp\EmptyDir /Purge
           }

Isso passará pelos caminhos que você fornecer na localização C:\Temp\DeleteDirectories e os excluirá.

Espero que isso ajude!

    
por 13.12.2016 / 13:41
0

É assim que você pode excluir pastas e arquivos com nomes de caminho realmente longos, embora não em powershell.

mkdir c:\alfa\bravo\charlie\delta\echo\foxtrot\golf\hotel\india\julliett\kilo\lima\mike\november\oscar\papa\quebec\romeo\sierra\tango\uniform\victor\whiskey\xray\yankee\zulu

join j: c:\alfa\bravo\charlie\delta\echo\foxtrot\golf\hotel\india\julliett
j:
subst k: j:\kilo\lima\mike\november\oscar\papa\quebec\romeo\sierra
k:
subst l: k:\tango\uniform\victor\whiskey
l:
rd /s/q xray
k:
rd /s/q tango
j:
rd /s/q kilo
c:
rd /s/q alfa

subst l: /d
subst k: /d
subst j: /d

O conceito geral é encadear vários comandos subst para que eles se aninhem profundamente na estrutura de pastas. Você pode ter que percorrer cerca de 6 letras de unidade. Em seguida, você pode começar a excluir pastas do nível mais profundo e, em seguida, percorrer o caminho de volta para cima & fora do caminho. Uma vez feito isso, você pode remover as letras de unidade criadas com o comando subst .

    
por 13.12.2016 / 14:30