Mova todos os arquivos e diretórios para um novo subdiretório no Windows

Mova todos os arquivos e diretórios para um novo subdiretório no Windows

Estou reorganizando os dados existentes e preciso criar um novo subdiretório para receber todos os arquivos e diretórios existentes. O objetivo disso é abrir espaço para uma nova linha de produtos e, ao mesmo tempo, melhorar a convenção de nomenclatura dos dados existentes.

Por exemplo, dados que atualmente se parecem com isto:

\root directory\
+-proj1357
  +-closing binder
  +-refi
  +-compliance
+-proj2468
  +-disbursements
  +-compliance
+-proj3579
  +-pre-close
  +-compliance

Na verdade deveria ficar assim:

\root directory\
+-proj1357
  +-dpl
    +-closing binder
    +-refi
    +-compliance
+-proj2468
  +-dpl
    +-disbursements
    +-compliance
+-proj3579
  +-dpl
    +-pre-close
    +-compliance

O problema que estou tendo é que não consigo obter o comando correto sem ficar preso em um loop recursivo. Ao hackear isso juntos, frequentemente encontrei o erro "não é possível executar uma cópia cíclica".

A boa notícia é que tenho uma solução funcional, mas requer três comandos separados e sintaxe personalizada para cada diretório de projeto.

command 1> ROBOCOPY G:\proj1357 DPL /E /MOVE
command 2> MOVE G:\proj1357\DPL\DPL\*.* G:\proj1357\DPL
command 3> RMDIR G:\proj1357\DPL\DPL\

Pelo que sei, o comando 1 move todos os arquivos e diretórios para o novo subdiretório. Também causa um problema recursivo ao mover arquivos do diretório no nível do projeto para um subdiretório mais profundo. Portanto, confio no Comando 2 para recuperar arquivos que já estiveram no diretório no nível do projeto. Em seguida, o Comando 3 remove o subdiretório mais profundo.

Existe uma maneira melhor de executar um comando ou arquivo em lote por meio de um sistema baseado em Windows? Idealmente, ele percorreria todos os diretórios no nível do projeto e moveria o conteúdo para o novo subdiretório. Estou pensando em processar mais de mil projetos, então acho que vale a pena descobrir como fazer o loop corretamente.

Para obter mais contexto visual do que estou enfrentando, veja a captura de tela abaixo. captura de tela do diretório do Windows


ATUALIZADA

Depois de tentar fazer funcionar usando o método de linha de comando de três etapas descrito acima, cedi e adaptei a resposta do jiggunjer para se adequar ao meu ambiente. Abaixo está o arquivo em lote do MS que usei. Também adicionei comentários para esclarecer o propósito de cada linha.

@echo off
rem run this batch file in top level directory
rem top level directory should contain all project number directories
rem assumes that all directories starting with a digit are project number directories 

rem initialize the listing of all directories
set rootlist=dir /b /a:D

rem initialize numerical filtering
set filter=findstr "^[1-9]"

rem loop through all directories that comply with filtering (start with a digit)
rem use command extension /F to process (in this case) command output
rem identifies all project number parent-directories
rem assign parent-directories to variable %%P, as in 'Project'
FOR /F %%P in ('%rootlist% ^| %filter%') DO (
    rem pass the variable %%P to the moveproject loop
    call :moveproject "%%P"
    
    rem move files that were ignored by the robocopy command
    rem these are 'loose' files that were in the project number directory, but not saved in any subdirectory
    rem assumes the robocopy command successfully creates the DPL directory
    MOVE %%P\*.* %%P\DPL\
)

rem pause to review command log
pause

:moveproject
rem ensure that the parameter has value
rem converts variable %%P to parameter no. 1
if not [%1] == [] (

rem loop through all sub-directories under each project number
rem use command extension /D to process directories only
rem removing any surrounding quotes (") from parameter no. 1 by using optional syntax -- percent-tilde
rem assign sub-directories to variable %%O, as in 'Origin'
FOR /D %%O IN ("%~1\*") DO (
    rem display values
    echo project number %%P
    echo directory origin %%O

    rem delimit origin directory using backslash character
    rem use command extension /F to process (in this case) strings
    rem assign the second delimited piece to variable %%D, as in 'Destination'
    rem effectively drops all text to the left of the first backslash character
    FOR /F "tokens=2 delims=\" %%D IN ("%%O") DO (
        rem display values
        echo %%D
        echo directory destination %%P\DPL\%%D
        
        rem move all directories to DPL sub-directory
        rem simultaniously creates the receiving DPL directory
        robocopy /E /MOVE "%%O" "%%P\DPL\%%D"
        )
    )
)

Responder1

Em cada um desses 8 diretórios raiz execute este comando:

FOR /D %p IN ("*") DO robocopy /E /MOVE "%p" "%p/DPL"

Versão Powershell 3.0+:

gci -dir -name | foreach-object{robocopy /E /MOVE $_ ($_ + '\DPL')}

OU

Com base na sua captura de tela, uma solução completa seria algo como:

@echo off
REM Assume: Running in top level dir. 
REM Assume: Only project parent fodlers start with a digit.
set rootlist=dir /b /a:D
set filter=findstr "^[1-9]"
FOR /f %%d in ('%rootlist% ^| %filter%') DO (
call :moveproject "%%d"
)

:moveproject
if not [%1] == [] (
FOR /D %%p IN ("%~1\*") DO robocopy /E /MOVE "%%p" "%%p/DPL"
)

Feliz re-paternidade!

Responder2

Você consegue fazer isso:

@echo off
mkdir %2
cd %1
SETLOCAL EnableDelayedExpansion
for /f "delims=" %%D in ('dir /a:d /b') do (
    set project_path=%%~fD
    move "!project_path!" "%~2%\temp"
    mkdir "!project_path!"
    move "%~2%\temp" "!project_path!\dpl"
)

Leva 2 parâmetros. O primeiro é o caminho que contém seus projetos, o segundo é o caminho temporário.

O que ele faz é simplesmente mover o projeto para um caminho temporário e, em seguida, movê-lo de volta para o antigo nome do projeto/dpl.

Nota: assume que o primeiro caminho contém apenas diretórios de projetos e irá ignorar não-diretórios neste nível.

informação relacionada