我正在尝试编写一个脚本,该脚本将查找磁盘上的所有目录连接,然后在另一个位置重新创建它们。首先,我必须找到所有连接并编辑输出以使其更易读。
这是测试.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”,而不是路径。如果我用任何字符串(例如“sausage”)替换“%start% %end%”,我得到的 output.txt 中就会充满香肠。如果我在脚本运行后运行 echo set %end%,输出将是“Templates”,这是预期的。我猜 set 命令在其中一个循环完成之前不会设置任何内容。
我说得对吗?有办法解决这个问题吗?我真的需要在 CMD 中运行它,因为它必须从 Windows 修复磁盘运行。
PS,我知道即使修复了这个程序,我的代码也无法达到我的目的,但我只是想先做最重要的事情。
答案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
)
)
我在这里做了另外两件事:-
- 我已经从不需要的命令中删除了括号(不幸的是,连续符后的新行
^
不能缩进,这会破坏第二个的格式if
)。 - 我删除了不必要的
for
循环,同时允许在目录和文件名中嵌入空格。
我把它们留在里面,但初始cd \
和set
初始化是不必要的,尽管你可能希望在退出之前清除start
它们end
。
答案2
替换并echo %start% %end% >> output.txt
附加call :forecho
最后一个脚本行下方的下一个代码片段:
goto :eof
:forecho
echo %start% %end% >> output.txt
goto :eof
问题实际上在于 %variables% 是在解析时逐条命令展开的,而不是在执行时展开的。并且所有括在(
括号中的代码片段)
都被视为唯一命令。
为了安全起见,脚本的开头应该是
@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