none
Script para apagar pastas e subpastas e deixar determinados arquivos RRS feed

  • Pergunta

  • Boa tarde,

    Senhores, necessito criar um script que apague algumas pastas e subpastas porém esta pastas e subpastas contém arquivos que não podem ser deletados. Estas pastas tem um padrão de nome que é DPT_000 onde o '000' é uma ordem numérica, por exemplo:

    C:\pasta_de_teste

    dentro da pasta_de_teste existe:

    DPT_001

    DPT_002

    e assim por diante. E dentro de cada pasta chamada DPT existe pastas chamadas A,B,C,D e dentro de cada pasta existe um .INI e as pastas as quais eu quero apagar.

    Cada vez que eu for rodas este VBS ou Power Shell ou qualquer outra forma, eu preciso deixar este .INI e a última pasta que foi criada.

    Já procurei alguns scripts e fiz algumas modificações porém não estou conseguindo deixar estas duas opções que eu citei acima.

    Agradeço desde já a ajuda.

    Obrigado!


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura

    segunda-feira, 4 de fevereiro de 2013 18:29

Respostas

  • Jeferson,

    Só não sei o que vc considera com última pasta: A com a data mais recente ou com o número maior (V222 > V221), no exemplo abaixo considerei o nome que tem o número maior.

    $PastaRoot="D:\Teste"
    
    #Pega lista de pastas do Nivel 1 (A, B, C, etc...)
    $PastasNivel_1 = Get-ChildItem $PastaRoot | where {$_.PsIsContainer}
    
    #Visita cada uma das pastas do nivel 1
    foreach ($Pasta_1 in $PastasNivel_1){
    
    
        #Pega lista de pastas do nivel 2 (A01, ...)
        $PastasNivel_2=Get-ChildItem $Pasta_1.FullName | where {$_.PsIsContainer}
    
        #Visita cada uma das pastas do nivel 2
        foreach  ($Pasta_2 in $PastasNivel_2){
    
            #Mais Recente (isto é uma única linha, quebrei no "|" apenas para melhor visuazualizar na tela)
            $MaisRecente=Get-ChildItem $Pasta_2.FullName | 
                where {$_.PsIsContainer} | 
                    sort LastWriteTime -Descending | 
                        select -first 1
    
            #Seleciona todas as pastas do nivel 3 menos a que tem o nome da mais recente
            $PastaNivel_3 = Get-ChildItem $Pasta_2.FullName | 
                where { ($_.PsIsContainer) -and ($_.name -ne $MaisRecente.name) } |
                     sort LastWriteTime -Descending
            
            #Apaga pastas
            $PastaNivel_3 | Remove-Item -Force
    
        }
        
    
    }


    Fábio de Paula Junior



    terça-feira, 5 de fevereiro de 2013 19:02
    Moderador

Todas as Respostas

  • Até o momento estou com um powershell que está quase fazendo o que eu estou querendo, porém não está verificando as subpastas.

    Comando em powershell:

     ls | where {$_.lastwritetime -lt (date).adddays(-1)} | foreach {rm $_ -whatif -Recurse}


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura

    segunda-feira, 4 de fevereiro de 2013 19:44
  • Jeferson,

    Se entendi então só falta o parâmetro -recurse no primeiro comando.

    ls -recurse | where {$_.lastwritetime -lt (date).adddays(-1)} | foreach {rm $_ -whatif -Recurse}


    Fábio de Paula Junior


    segunda-feira, 4 de fevereiro de 2013 19:51
    Moderador
  • Se puder dar um exemplo prático: antes e como deve ficar depois.

    Fábio de Paula Junior

    segunda-feira, 4 de fevereiro de 2013 19:53
    Moderador
  • Opa, Bom dia Fábio,

    Deixa eu ver se eu consigo me explicar melhor para você entender o meu problema.

    Por exemplo, estou com uma estrutura D:\Teste.

    Dentro desta estrutura existe as pastas A,B,C,D. Dentro de A existe a pasta A01 e dentro desta pasta existe um arquivo *.ini e várias pastas em ordem crescente como por exemplo V01243, V01242 e assim por diante em cada pasta (B,C,D)

    ###############################################

    D:\Teste

    ___>A
    |___A01
    |___ *.ini (arquivo)
    |___  V01243 (pasta)
    |___ V01242 (pasta)

    ___>B
    |___B01
    |___ *.ini (arquivo)
    |___  V02243 (pasta)
    |___ V02242 (pasta)

    ___>C
    |___C01
    |___ *.ini (arquivo)
    |___  V03243 (pasta)
    |___ V03242 (pasta)

    ##################################################

    O que eu preciso é sempre deixar este arquivo *.ini e a última pasta que foi gravada (Ex: V01243 e apagar as outras que estão em sequencia)

    ##################################################

    ___>A
    |___A01
    |___ *.ini (arquivo)
    |___  V01243 (pasta)

    ___>B
    |___B01
    |___ *.ini (arquivo)
    |___  V02243 (pasta)

    ___>C
    |___C01
    |___ *.ini (arquivo)
    |___  V03243 (pasta)

    ########################################

    Obrigado pela atenção!


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura

    terça-feira, 5 de fevereiro de 2013 11:29
  • Senhores,

    Já consigo listar todo o conteúdo pela data pelo comando:

    # ls -recurse | where {$_.lastwritetime -le (get-date).adddays(-1)}

    e já consigo ver as extenções da pasta raíz e armazenar em um arquivo com o comando:

    # ls | Select-Object Extension | Sort-Object Extension | Get-Unique -AsString | out-file unidade:\pasta\arquivo.txt

    mas como juntar os dois comando para funcionar corretamente ?


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura


    terça-feira, 5 de fevereiro de 2013 16:59
  • Jeferson,

    Só não sei o que vc considera com última pasta: A com a data mais recente ou com o número maior (V222 > V221), no exemplo abaixo considerei o nome que tem o número maior.

    $PastaRoot="D:\Teste"
    
    #Pega lista de pastas do Nivel 1 (A, B, C, etc...)
    $PastasNivel_1 = Get-ChildItem $PastaRoot | where {$_.PsIsContainer}
    
    #Visita cada uma das pastas do nivel 1
    foreach ($Pasta_1 in $PastasNivel_1){
    
    
        #Pega lista de pastas do nivel 2 (A01, ...)
        $PastasNivel_2=Get-ChildItem $Pasta_1.FullName | where {$_.PsIsContainer}
    
        #Visita cada uma das pastas do nivel 2
        foreach  ($Pasta_2 in $PastasNivel_2){
    
            #Mais Recente (isto é uma única linha, quebrei no "|" apenas para melhor visuazualizar na tela)
            $MaisRecente=Get-ChildItem $Pasta_2.FullName | 
                where {$_.PsIsContainer} | 
                    sort LastWriteTime -Descending | 
                        select -first 1
    
            #Seleciona todas as pastas do nivel 3 menos a que tem o nome da mais recente
            $PastaNivel_3 = Get-ChildItem $Pasta_2.FullName | 
                where { ($_.PsIsContainer) -and ($_.name -ne $MaisRecente.name) } |
                     sort LastWriteTime -Descending
            
            #Apaga pastas
            $PastaNivel_3 | Remove-Item -Force
    
        }
        
    
    }


    Fábio de Paula Junior



    terça-feira, 5 de fevereiro de 2013 19:02
    Moderador
  • Fábio,

    Primeiramente obrigado pelo auxilio.

    No caso, até poderíamos considerar o que tem maior valor como o mais recente, porém caso o contator chegasse no limite e começasse novamente teríamos problema certo ?

    Então acho que o mais viável seria considerar o que foi alterado recentemente como o mais atualizado. Neste caso o que mudaria em seu script ?

    Agradeço sua ajuda!


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura

    terça-feira, 5 de fevereiro de 2013 19:51
  • Jeferson,

    Perfeito seu raciocinio, então basta utilizar outro atributo, eu coloquei em ordem de nome(descendente) então temos que mudar para algo como LastWriteTime.

    Então troque isso:

    #Seleciona todas as pastas do nivel 3 menos a que tem o nome da mais recente
            $PastaNivel_3 = Get-ChildItem $Pasta_2.FullName | 
                where { ($_.PsIsContainer) -and ($_.name -ne $MaisRecente.name) } |
                     sort Name -Descending

    por isto:

    #Seleciona todas as pastas do nivel 3 menos a que tem o nome da mais recente
            $PastaNivel_3 = Get-ChildItem $Pasta_2.FullName | 
                where { ($_.PsIsContainer) -and ($_.name -ne $MaisRecente.name) } |
                     sort LastWriteTime -Descending

    Não testei, e já corrigi no código que postei anteriormente.


    Fábio de Paula Junior

    terça-feira, 5 de fevereiro de 2013 22:43
    Moderador
  • E isso

    $MaisRecente=Get-ChildItem $Pasta_2.FullName | 
                where {$_.PsIsContainer} | 
                    sort Name -Descending | 
                        select -first 1

    por

    $MaisRecente=Get-ChildItem $Pasta_2.FullName | 
                where {$_.PsIsContainer} | 
                    sort LastWriteTime -Descending | 
                        select -first 1


    Fábio de Paula Junior

    terça-feira, 5 de fevereiro de 2013 22:47
    Moderador
  • Boa tarde Fábio,

    Realizei alguns testes aqui com o seu script e aparentemente funcionou mas me pediu confirmação para cada execução que o mesmo fazia em cada pasta.

    Teria como colocar algum parâmetro para não pedir confirmação ?

    Agradeço sua ajuda!

    Obrigado!


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura

    quarta-feira, 6 de fevereiro de 2013 17:32
  • Eu achava que com o -force removia esta mensagem de confirmação (inclusive nos testes que realizei funcionou bem), mas segundo o artigo abaixo tem que usar o -recurse

    How to Force ‘Remove-Item’ to Delete Items and Suppress the Confirmation Prompt in Windows PowerShell

    http://thenubbyadmin.com/2011/09/29/how-to-force-remove-item-to-delete-items-and-suppress-the-confirmation-prompt-in-windows-powershell/


    Fábio de Paula Junior

    quarta-feira, 6 de fevereiro de 2013 17:36
    Moderador
  • Fábio,

    Efetuei o teste com o -Recurse, ele removeu os itens corretamente mas apresentou um erro:

    Remove-Item : Não é possível associar o argumento ao parâmetro 'Path' porque ele é nulo.
    Em D:\testar.ps1:26 caractere:36
    +         $PastaNivel_3 | Remove-Item <<<<  -Force -Recurse
        + CategoryInfo          : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveItemCommand

    saberia me dizer o motivo pelo qual está apresentando este erro ?

    E aproveitando a deixa, para colocar estre script para rodar no Windows server 2003 teria como ? Li uma vez um artigo que teria que fazer a instalação de um Pacth do Windows 2003 para poder rodar.

    Agradeço sua dedicação!

    Abraço!


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura

    quarta-feira, 6 de fevereiro de 2013 18:09
  • Não tenho certeza mas pode ser um caso em que a variavel $PastaNivel_3 esteja vazia (pois na pasta só tinha uma subpasta).

    Pode tentar trocar isto:

    $PastaNivel_3 | Remove-Item -Force -Recurse

    por isso

    if ($PastaNivel_3.count -gt 0){ $PastaNivel_3 | Remove-Item -Force -Recurse }

    O que eu fiz foi verificar se a variavel $PastaNivel_3 é maior que Zero, só se esta condição for satisfeita ele tenta apagar as pastas.


    Fábio de Paula Junior


    quarta-feira, 6 de fevereiro de 2013 20:09
    Moderador
  • Fábio,

    Vou fazer os testes aqui e posto o resultado.

    Obrigado pela sua ajuda!


    Att, Jeferson Madruga da Rosa - Administrador de Redes / Infraestrutura

    quinta-feira, 7 de fevereiro de 2013 10:57
  • Jeferson, Conseguiu ?

    Fábio de Paula Junior

    terça-feira, 19 de fevereiro de 2013 18:25
    Moderador