2

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

Это 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

- Это (незаконченный) скрипт, который я запускаю:

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

          )
       )
    )
 )
)
)

Проблема в том, что output.txt заканчивается несколькими строками "Echo is ON" вместо путей в них. Если я заменю «% start%% end%» какой-либо строкой (например, "sausage"), я получаю output.txt, заполненный сосисками. Если я запускаю echo set% end% после запуска скрипта, выводится "Шаблоны", что и ожидается. Я предполагаю, что команда set ничего не устанавливает, пока один из циклов не будет выполнен.

Я прав? Есть ли способ обойти это? Мне действительно нужно, чтобы это работало в CMD, потому что оно должно запускаться с диска восстановления Windows.

PS Я знаю, что мой код не будет работать для моих целей, даже если эта программа исправлена, но я только начинаю, обо всем по порядку.

2 ответа2

1

Замените echo %start% %end% >> output.txt на call :forecho и присоедините следующий фрагмент кода под последней строкой скрипта:

goto :eof

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

Проблема заключается в том, что% переменные% раскрываются, команда за командой, во время разбора, а не во время выполнения. И весь фрагмент кода, заключенный в ( круглые скобки ) , считается единственной командой.

Чтобы быть в безопасности, начните свой сценарий с

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion

Весь сценарий тогда может быть следующим:

@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
1

Если вы используете свой оригинальный скрипт и добавляете setlocal enabledelayedexpansion вы можете заменить %start% и %end% на !start! и !end! и ваш сценарий будет работать так, как вы хотели.

Ваш скрипт не допускает пробелов в именах файлов, поэтому я предлагаю следующий модифицированный скрипт:-

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

        )
)

Я сделал две дополнительные вещи здесь:

  1. Я удалил квадратные скобки из команд, которые не нуждаются в этом (к сожалению, новая строка после символа продолжения ^ не может иметь отступ, что портит форматирование второго if).
  2. Я удалил ненужные for петель в то же время позволяя вложенных пробелов в именах каталогов и файлов.

Я оставил их внутри, но инициализация cd \ и set не нужны, хотя вы можете очистить start и end перед выходом.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .