5

I'm working in Windows and would like to know if there is a way to remove the current working directory from the path? I understand that this is the default behavior in PowerShell, but I need it to work in batch or at the Windows command-line.

In UNIX, I would just make sure that my $PATH variable not contain .. Is there any way to accomplish this in batch? This is the current behavior:

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>

This is the desired behavior:

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>

Thanks.

aschipfl
  • 33,626
  • 12
  • 54
  • 99
Tripp Kinetics
  • 5,178
  • 2
  • 23
  • 37
  • 2
    You are basically asking to change the behavior of Windows. Windows will always search the current directory first. Then search the %path% variable and finally search the registry. The only option I see for you is to make it look in the directory one level above. `..\dwk.bat` – Squashman Apr 27 '18 at 14:52
  • Yes, I am trying to change the default behavior of Windows. As I said, it's trivial to do so in UNIX or PowerShell. – Tripp Kinetics Apr 27 '18 at 15:22
  • I'm intrigued, how do you do it in UNIX? and PowerShell? i.e. change their shells default behavior, so that `.\dwk.bat` does not search in the current working directory! – Compo Apr 27 '18 at 15:37
  • That is not what I'm asking. Please read the question again. – Tripp Kinetics Apr 27 '18 at 15:52
  • 1
    @compo Both shells don't default search in current dir, you have to prefix with `.\ resp. ./` In powershell you automate this with tab. –  Apr 27 '18 at 15:54
  • 1
    @Tripp, did you not say that it's trivial to change the default behavior in UNIX or Powershell. The default behavior is that .\ searches in the current directory, so show me how trivial it is to change that default behaviour! Unless you can programmatically do so, I don't see how your question is relevant here. – Compo Apr 27 '18 at 16:37
  • No, it is not trivial to change that behavior, but that is not the behavior I am trying to change. – Tripp Kinetics Apr 27 '18 at 20:19
  • I am trying to REQUIRE the `.\` . – Tripp Kinetics Apr 27 '18 at 20:20
  • In PowerShell and sh, you just leave `.` out of the path in order to get the behavior I want. Trivial. – Tripp Kinetics Apr 27 '18 at 20:53
  • it's hardcoded. You'd have to hack `cmd.exe` and then talk Windows into accepting the changed `cmd.exe` – Stephan Apr 27 '18 at 21:02

1 Answers1

4

I recommend first reading the answers on Stack Overflow questions:

Many thanks to eryksun because of this answer would not exist without his comment on above referenced answer.

Next I recommend reading the Microsoft Developer Network (MSDN) articles:

The question can be answered with: Yes, it is possible for desktop applications and batch files on

  • Windows Vista and all later Windows client versions and
  • Windows Server 2003 and all later Windows Server versions.

An environment variable with name NoDefaultCurrentDirectoryInExePath must be defined with any value to prevent execution of a script (.bat, .cmd, .vbs, ...) or an application (.com, .exe) stored in current directory without explicitly using .\ as required on Unix/Linux.

The environment variable NoDefaultCurrentDirectoryInExePath can be defined as system variable to turn off searching in current directory for a script or application for all accounts on this machine. But this is surely no good idea as it will result definitely in many applications including installers and uninstallers won't work anymore correct.

The environment variable NoDefaultCurrentDirectoryInExePath can be defined as user variable to turn off searching in current directory for a script or application for processes using this account. But this is surely also no good idea.

But it can make sense to set the environment variable NoDefaultCurrentDirectoryInExePath as local variable in some use cases to turn off searching in current directory for a script or application without explicitly using .\ on Windows versions with kernel function NeedCurrentDirectoryForExePath which cmd.exe calls before searching for a script file or application not containing a backslash \ (or a forward slash /) in file name string.

Example:

@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

This batch file executed from within a command prompt window results in output of current console window:

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 . . . 

And during execution of this batch file a second console window is opened with output:

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

This second console window is closed automatically after 5 seconds.

The environment variable NoDefaultCurrentDirectoryInExePath is defined with value 0 after setting directory for temporary files as current directory with pushing current directory path on stack. The variable value does not matter because of evaluated is only existence of environment variable and not its value.

Next another batch file with name Test1.bat is created in directory for temporary files which is usually not write-protected for current user as this would cause lots of troubles.

The first approach to call Test1.bat without any path fails because of environment variable NoDefaultCurrentDirectoryInExePath is defined in local environment.

The second call of Test1.bat with relative path .\ is successful despite existence of the environment variable.

The command START ignores NoDefaultCurrentDirectoryInExePath as proven by this batch file.

Then the environment variable NoDefaultCurrentDirectoryInExePath is deleted to restore original Windows behavior.

The second approach to call Test1.bat without any path is successful now.

Finally the created Test1.bat is deleted and initial current directory is restored as current directory.

It is of course not possible to prevent execution of command DIR which is not a script file or an executable. It is an internal command of cmd.exe – Windows Command Processor – respectively of powershell.exe – Windows PowerShell.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • 1
    +1! That is great information. I can see how that could come in handy if for example you named your batch file ping.bat and then use `ping google.com` in your batch file. – Squashman May 01 '18 at 15:28
  • Thank you very, very much @Mofi! This is precisely what I was looking for! – Tripp Kinetics May 01 '18 at 15:30
  • 1
    I found another comment from eryksun in another question that said setting the variable to 1 also changes its behavior. So does the variable just need to be defined or does setting it to 0 or 1 change the environment behavior. – Squashman May 01 '18 at 16:17
  • 1
    This confusion comes from __Remarks__ section in the MSDN article about function [NeedCurrentDirectoryForExePath](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684269.aspx) which contains the sentence: *The value of the NoDefaultCurrentDirectoryInExePath environment variable determines the value this function returns.* But in next paragraph is written: *... the existence of the NoDefaultCurrentDirectoryInExePath environment variable is checked, and not its value.* I used in my example `0` as value. But the value can be also `hello world`. The variable existence matters, not value. – Mofi May 01 '18 at 16:26