从路径中删除当前工作目录

5
我正在使用Windows,想知道是否有一种方法可以将当前工作目录从路径中删除?我知道PowerShell默认会这样做,但是我需要在批处理或Windows命令行下工作。
在UNIX中,我只需要确保我的$PATH变量不包含“.”。是否有办法在批处理中实现这一点?这是当前的行为:
H:\tmp>dir
 Volume in drive H has no label.
 Volume Serial Number is E29C-7B61

 Directory of H:\tmp

04/27/2018  10:39 AM    <DIR>          .
04/27/2018  10:39 AM    <DIR>          ..
04/27/2018  10:40 AM                37 dwk.bat
               1 File(s)             37 bytes
               2 Dir(s)  987,995,770,880 bytes free

H:\tmp>dwk.bat
dwk.bat has been run.

H:\tmp>

这是期望的行为:
H:\tmp>dwk.bat
'dwk.bat' is not recognized as an internal or external command,
operable program or batch file.

H:\tmp>.\dwk.bat
dwk.bat has been run.

H:\tmp>

感谢您的选择。

2
你基本上是在要求更改Windows的行为。Windows将始终首先搜索当前目录,然后搜索%path%变量,最后搜索注册表。我看到你唯一的选择是让它查找上一级目录中的文件。 ..\dwk.bat - Squashman
是的,我正在尝试更改Windows的默认行为。正如我所说,在UNIX或PowerShell中这样做非常容易。 - Tripp Kinetics
我很感兴趣,你如何在UNIX和PowerShell中实现它?即更改它们的shell默认行为,以便.\dwk.bat不会在当前工作目录中搜索! - Compo
1
@compo 两个 shell 都不会默认在当前目录中搜索,你需要使用 .\ 或者 ./ 前缀。在 PowerShell 中,你可以通过 tab 键自动完成这个操作。 - user6811411
1
@Tripp,你不是说在UNIX或Powershell中更改默认行为很容易吗?默认行为是.\在当前目录中搜索,那么请展示一下如何轻松更改该默认行为!除非你可以以编程方式这样做,否则我不明白你的问题在这里有什么相关性。 - Compo
显示剩余5条评论
1个回答

5
我建议首先阅读Stack Overflow问题的答案: 感谢eryksun,由于上述引用的答案他的评论,才使本答案存在。
接下来,我建议阅读Microsoft Developer Network(MSDN)文章: 问题的答案是:对于桌面应用程序和批处理文件,在以下Windows客户端版本和Windows Server版本中均可实现:
  • Windows Vista及更高版本
  • Windows Server 2003及更高版本。
必须定义名称为NoDefaultCurrentDirectoryInExePath的环境变量,并为其赋任何值,以防止在未显式使用.\的情况下执行存储在当前目录中的脚本(.bat、.cmd、.vbs等)或应用程序(.com、.exe),这在Unix/Linux上是必需的。
可以将环境变量NoDefaultCurrentDirectoryInExePath定义为系统变量,以关闭对此计算机上所有帐户的脚本或应用程序在当前目录中搜索的功能。但这肯定不是一个好主意,因为它肯定会导致许多应用程序(包括安装程序和卸载程序)不能正确运行。
可以将环境变量NoDefaultCurrentDirectoryInExePath定义为用户变量,以关闭针对使用此帐户的进程在当前目录中搜索脚本或应用程序的功能。但这也肯定不是一个好主意。
但是,在某些用例中,将环境变量NoDefaultCurrentDirectoryInExePath设置为本地变量可能是有意义的,以在Windows版本上关闭在当前目录中搜索脚本或应用程序的功能,该版本具有内核函数NeedCurrentDirectoryForExePath,在搜索不包含反斜杠\(或正斜杠/)的文件名字符串的脚本文件或应用程序之前,cmd.exe调用该内核函数。
例如:
@echo off
pushd "%TEMP%"
set "NoDefaultCurrentDirectoryInExePath=0"

echo @echo %%0 executed successfully.>Test1.bat

echo Calling Test1.bat ...
call Test1.bat

echo Calling .\Test1.bat ...
call .\Test1.bat

echo Starting Test1.bat ...
start /wait Test1.bat ^& timeout 5

set "NoDefaultCurrentDirectoryInExePath="

echo Calling again Test1.bat ...
call Test1.bat

del Test1.bat
popd
pause

在命令提示符窗口中执行此批处理文件,将导致输出当前控制台窗口:

Calling Test1.bat ...
'Test1.bat' is not recognized as an internal or external command,
operable program or batch file.
Calling .\Test1.bat ...
.\Test1.bat executed successfully.
Starting Test1.bat ...
Calling again Test1.bat ...
Test1.bat executed successfully.
Press any key to continue . . . 

在执行此批处理文件期间,会打开第二个控制台窗口并显示输出:

"%TEMP%\Test1.bat" executed successfully.

5秒后第二个控制台窗口将自动关闭。

环境变量NoDefaultCurrentDirectoryInExePath被定义为0,并将临时文件的目录设置为当前目录,并将当前目录路径推入堆栈中。由于只评估环境变量的存在而不是其值,因此变量值并不重要。

接下来,在通常对于当前用户没有写保护的临时文件目录中创建了另一个名为Test1.bat的批处理文件,因为这会引起许多麻烦。

首先尝试使用没有任何路径的方式调用Test1.bat,但由于存在本地环境中的环境变量NoDefaultCurrentDirectoryInExePath,因此失败了。

第二次使用相对路径.\调用Test1.bat成功,尽管存在环境变量。

START命令忽略NoDefaultCurrentDirectoryInExePath,这在这个批处理文件中得到了证明。

然后删除环境变量NoDefaultCurrentDirectoryInExePath以恢复原始的Windows行为。

现在再次尝试使用没有任何路径的方式调用Test1.bat,这次成功了。

最后删除创建的Test1.bat文件,并将初始当前目录恢复为当前目录。

当然,无法阻止执行DIR命令,因为它不是脚本文件或可执行文件。它是cmd.exe - Windows命令处理器 - 或powershell.exe - Windows PowerShell的内部命令。


1
+1!这是很棒的信息。我可以看出如果你将批处理文件命名为ping.bat,然后在批处理文件中使用ping google.com,这会非常方便。 - Squashman
非常感谢您,@Mofi!这正是我在寻找的! - Tripp Kinetics
1
我在另一个问题中发现了 eryksun 的另一条评论,他说将变量设置为 1 也会改变其行为。那么这个变量只需要被定义还是将其设置为 0 或 1 会改变环境的行为呢? - Squashman
2
这种混淆来自于MSDN文章中关于函数NeedCurrentDirectoryForExePath的__Remarks__部分,其中包含以下句子:NoDefaultCurrentDirectoryInExePath环境变量的值决定了此函数返回的值。 但在下一段中写道:*...检查的是NoDefaultCurrentDirectoryInExePath环境变量的存在,而不是它的值。* 我在我的示例中使用了0作为值。但是该值也可以是hello world。变量的存在很重要,而不是值。 - Mofi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接