Definir configuração não no script de lote do CMD

2

Estou tentando escrever um script que encontre todas as junções de diretório em um disco e, em seguida, as recrie em outro local. Primeiro de tudo, eu tenho que encontrar todas as junções e editar a saída para ser mais legível.

Este é o test.txt:

 Volume in drive C has no label.
 Volume Serial Number is A0D2-DFB0

 Directory of C:\

14.07.2009.  06:08    <JUNCTION>     Documents and Settings [C:\Users]
13.01.2015.  10:26    <JUNCTION>     Users [E:\Users]
               0 File(s)              0 bytes

 Directory of C:\ProgramData

14.07.2009.  06:08    <JUNCTION>     Application Data [C:\ProgramData]
14.07.2009.  06:08    <JUNCTION>     Desktop [C:\Users\Public\Desktop]
14.07.2009.  06:08    <JUNCTION>     Documents [C:\Users\Public\Documents]
14.07.2009.  06:08    <JUNCTION>     Favorites [C:\Users\Public\Favorites]
14.07.2009.  06:08    <JUNCTION>     Start Menu [C:\ProgramData\Microsoft\Windows\Start Menu]
14.07.2009.  06:08    <JUNCTION>     Templates [C:\ProgramData\Microsoft\Windows\Templates]
               0 File(s)              0 bytes

 Directory of C:\ProgramData\Oracle\Java\javapath

24.12.2014.  18:22    <SYMLINK>      java.exe [D:\Programs\Java 8u25\bin\java.exe]
24.12.2014.  18:22    <SYMLINK>      javaw.exe [D:\Programs\Java 8u25\bin\javaw.exe]
24.12.2014.  18:22    <SYMLINK>      javaws.exe [D:\Programs\Java 8u25\bin\javaws.exe]
               3 File(s)              0 bytes

     Total Files Listed:
               3 File(s)              0 bytes
               8 Dir(s)  16.309.276.672 bytes free

Este é o script (inacabado) que estou executando:

echo on

cd \

set start=
set end=
set paths=

type NUL > output.txt

for /f "tokens=* skip=3" %%l in (C:\test.txt) do (
for /f "tokens=1" %%d in ("%%l") do (
 if %%d==Directory (
    for /f "tokens=3" %%p in ("%%l") do (
      set start="%%p"
    )
 ) else (
   for /f "tokens=3" %%j in ("%%l") do (
      if %%j==^<JUNCTION^> (
          for /f "tokens=4*" %%h in ("%%l") do (
            set end="%%h"
            echo %start% %end% >> output.txt

          )
       )
    )
 )
)
)

O problema é que o output.txt termina com várias linhas de "Echo is ON" em vez de ter caminhos lá. Se eu substituir "% start%% end%" por qualquer string (por exemplo, "sausage") recebo output.txt cheio de salsichas. Se eu executar o echo set% end% após a execução do script, a saída será "Templates", o que é esperado. Eu estou supondo que o comando set não define nada até que um dos loops esteja concluído.

Estou certo? Existe uma maneira de contornar isso? Eu realmente preciso fazer isso funcionar no CMD porque tem que ser executado a partir do disco de reparação do Windows.

P.S. Eu sei que o meu código não funciona para o meu propósito, mesmo com este programa consertado, mas eu estou chegando lá, as primeiras coisas primeiro.

    
por Karlovsky120 14.01.2015 / 23:13

2 respostas

1

Se você usar seu script original e adicionar setlocal enabledelayedexpansion , poderá substituir %start% e %end% por !start! e !end! e seu script funcionará como você pretendia.

Seu script não permite espaços em branco nos nomes dos arquivos, então proponho o seguinte script modificado: -

echo off

setlocal enabledelayedexpansion

cd \

set start=
set end=
set paths=

type NUL > output.txt

for /f "tokens=* skip=3" %%l in (C:\test.txt) do ^
for /f "tokens=1-2*" %%d in ("%%l") do ^
if %%d==Directory (
    set start="%%f"
) else (
    for /f "tokens=3*" %%j in ("%%l") do ^
if %%j==^<JUNCTION^> (
            for /f "tokens=1 delims=[" %%n in ("%%k") do set end=%%n
            set end="!end:~0,-1!"
            echo !start! !end! >> output.txt

        )
)

Eu fiz duas coisas adicionais aqui: -

  1. Eu removi os colchetes dos comandos que não precisam dele (infelizmente, a nova linha após o caractere de continuação ^ não pode ser recuada, o que estraga a formatação do segundo if ).
  2. Eu removi for loops desnecessários enquanto ao mesmo tempo permitia espaços em branco incorporados nos nomes de diretórios e arquivos.

Deixei-os, mas as inicializações cd \ e set são desnecessárias, embora você queira limpar start e end antes de sair.

    
por 15.01.2015 / 15:19
1

Substitua echo %start% %end% >> output.txt por call :forecho e anexe o próximo trecho de código abaixo da última linha de script:

goto :eof

:forecho
    echo %start% %end% >> output.txt
goto :eof

O problema estabelece que% variáveis% são expandidas, comando por comando, em tempo de análise e não em tempo de execução. E todo o snippet de código entre ( parenthheses ) é considerado como um único comando.

Para garantir, comece seu script com

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion

O script completo pode ser o seguinte:

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion
cd \
set start=
set end=
set paths=
type NUL > output.txt

for /f "tokens=* skip=3" %%l in (C:\test.txt) do (
for /f "tokens=1" %%d in ("%%l") do (
 if %%d==Directory (
    for /f "tokens=3" %%p in ("%%l") do (
      set start="%%p"
    )
 ) else (
   for /f "tokens=3" %%j in ("%%l") do (
      if %%j==^<JUNCTION^> (
          for /f "tokens=4*" %%h in ("%%l") do (
            set end="%%h"
            call :forecho
          )
       )
    )
 )
)
)
@ENDLOCAL
goto :eof

:forecho
    echo %start% %end% >> output.txt
goto :eof
    
por 15.01.2015 / 11:52