我有一个批处理文件,与我想要xcopy
的文件位于同一目录中。但由于某种原因,找不到该文件。
我认为当前目录始终是批处理文件所在的位置。
我以管理员身份运行批处理文件。这种情况发生在Windows 7 64位台式计算机上。
批处理文件:
@ECHO OFF
XCOPY /y "File1.txt" "File2.txt"
PAUSE
错误:
File not found - File1.txt
0 File(s) copied
答案 0 :(得分:20)
使用上下文菜单项以管理员身份运行启动批处理文件时,当前工作目录是哪个目录取决于当前用户的用户帐户控制(UAC)设置。 / p>
这可以通过以下小批量文件C:\Temp\Test.bat
来证明:
@echo Current directory is: %CD%
@pause
在用户帐户控制设置
中选择默认 - 仅在程序尝试更改计算机时通知我
- 当我更改Windows设置时,请不要通知我
并使用以管理员身份运行,Windows使用注册表项
HKEY_CLASSES_ROOT\batfile\shell\runasuser\command
此注册表项不包含用于执行批处理文件的默认字符串。相反,字符串值DelegateExecute
的CLSID为{ea72d00e-4960-42fa-ba92-7792a7944c1d}
。
结果是打开一个标题为用户帐户控制和文本
的对话框窗口是否要允许以下程序对此计算机进行更改?
程序名称:Windows命令处理器
已验证的发布者:Microsoft Windows
在用户确认后,Windows会暂时打开一个新的用户会话,就像在命令行RunAs上使用一样。
在这个新的用户会话中,当前工作目录为%SystemRoot%\System32
,现在执行Windows注册表中定义的命令,默认字符串为key
HKEY_CLASSES_ROOT\batfile\shell\runas\command
是:
%SystemRoot%\System32\cmd.exe /C "%1" %*
因此打开一个控制台窗口,标题为 C:\ Windows \ System32 \ cmd.exe 和2行:
Current directory is: C:\Windows\System32
Press any key to continue . . .
点击任意键后,批处理执行完成,导致关闭cmd.exe
,从而导致关闭用户会话。
但已选择用户帐户控制设置
时不要通知我
程序尝试安装软件或对计算机进行更改
我对Windows设置进行了更改
行为不同,因为用户已经提升了权限。
现在Windows直接使用命令
%SystemRoot%\System32\cmd.exe /C "%1" %*
根据密钥的默认字符串
HKEY_CLASSES_ROOT\batfile\shell\runas\command
在当前用户会话中。
结果是打开一个标题为 C:\ Windows \ System32 \ cmd.exe 的控制台窗口,但在窗口中显示为:
Current directory is: C:\Temp
Press any key to continue . . .
父进程的当前工作目录(Windows资源管理器作为桌面)用于执行批处理文件,因为在这种情况下不需要切换到其他用户会话。
PA在他的回答中已经发布了2个可能的解决方案,我在这里复制了一个小的改进(pushd
目录用双引号)并添加了第三个。
使用 pushd 和 popd 将当前目录更改为批处理文件目录:
pushd "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
popd
这也适用于UNC路径。在命令提示符窗口pushd /?
中运行,以解释为什么这也适用于UNC路径。
在源和目标规范中使用批处理文件的目录:
%SystemRoot%\System32\xcopy.exe "%~dp0File1.txt" "%~dp0File2.txt" /Y
使用 cd :
将工作目录更改为批处理文件的目录cd /D "%~dp0"
%SystemRoot%\System32\xcopy.exe "File1.txt" "File2.txt" /Y
这对UNC路径不起作用,因为命令解释程序 cmd 默认情况下不支持将UNC路径作为当前目录,有关详细信息,请参阅示例CMD does not support UNC paths as current directories。
答案 1 :(得分:2)
错误消息非常自我解释。找不到文件file1.txt
。
由于文件名不包含绝对路径,因此系统会尝试在当前目录中找到它。您当前的目录不包含此文件。
您的误解是当前目录不是包含bat文件的目录。这是两个不相关的概念。
您可以通过在bat文件中添加这两个命令轻松检查
echo BAT directory is %~dp0
echo Current directory is %CD%
您可以注意到它们是不同的,并且最后一个反斜杠的添加方式存在细微差别。
所以,实际上有两种方法可以解决这个问题
更改当前目录以匹配预期的目录
pushd %~dp0
XCOPY /y "File1.txt" "File2.txt"
popd
或在命令
中指定完整路径XCOPY /y "%~dp0File1.txt" "%~dp0File2.txt"
答案 2 :(得分:1)
为了完整性和默默无闻,我添加了另一种解决方法,确认在Windows 8.1下工作并期望在其他地方工作,因为它依赖于记录的功能:
您可以更改runas
命令定义键
HKEY_CLASSES_ROOT\batfile\shell\runas\command
和
HKEY_CLASSES_ROOT\cmdfile\shell\runas\command
进入
%SystemRoot%\System32\cmd.exe /S /C "(for %%G in (%1) do cd /D "%%~dpG") & "%1"" %*
当使用bat
动词分别以“以管理员身份运行”菜单项启动时,会导致cmd
或runas
文件从其包含目录开始。
原始命令的添加内容恰好如下:
cmd /S
在/C
for %%G in (%1) do
枚举其单个条目%1
参数,
使它可以在循环体中以%%G
扩展;这封信是任意的,但有些可能是“保留”%%~dpG
扩展到%%G
的 d 和 p ath,〜代替剥离引号如果存在,这就是我们明确添加它们的原因cd /D
将 d 铆钉和目录更改为其参数,最后&
运行第二个命令"%1" %*
,无论第一个命令是否成功。 你可以使用甚至支持UNC路径的pushd
,但是迷路popd
会将任何脚本放在system32
目录中,而不是行为I会喜欢的。
可能会打破很多。
享受击败操作系统的安全机制:)