- path path
- Синтаксис Syntax
- Параметры Parameters
- Комментарии Remarks
- Примеры Examples
- Executable search path windows
- Permanent Changes
- PathExt
- Dpath
- Terminology — filename, path, pathname
- Paths for GUI Windows applications
- Errorlevels
- Modifying the “Path to executable” of a windows service
- 8 Answers 8
- Finding current executable’s path without /proc/self/exe
- 14 Answers 14
path path
Задает путь к команде в переменной среды PATH, указывающий набор каталогов, используемых для поиска исполняемых файлов (exe). Sets the command path in the PATH environment variable, specifying the set of directories used to search for executable (.exe) files. При использовании без параметров эта команда отображает текущий путь к команде. If used without parameters, this command displays the current command path.
Синтаксис Syntax
Параметры Parameters
Параметр Parameter | Описание Description |
---|---|
[ :] |
Комментарии Remarks
Операционная система Windows выполняет поиск по расширениям имен файлов по умолчанию в следующем порядке приоритета: exe, com, bat и cmd. The Windows operating system searches using default file name extensions in the following order of precedence: .exe, .com, .bat, and .cmd. Это означает, что если вы ищете пакетный файл с именем, acct.bat, но у вас есть приложение с именем acct.exe в том же каталоге, необходимо включить расширение bat в командную строку. Which means if you’re looking for a batch file named, acct.bat, but have an app named acct.exe in the same directory, you must include the .bat extension at the command prompt.
Если два или более файлов в пути команды имеют одинаковое имя файла и расширение, эта команда сначала выполняет поиск указанного имени файла в текущем каталоге. If two or more files in the command path have the same file name and extension, this command first searches for the specified file name in the current directory. Затем он ищет каталоги в пути команды в том порядке, в котором они указаны в переменной среды PATH. Then, it searches the directories in the command path in the order that they’re listed in the PATH environment variable.
При помещении команды path в файл AUTOEXEC. NT операционная система Windows автоматически добавляет указанный путь поиска подсистемы MS-DOS при каждом входе в систему. If you place the path command in your Autoexec.nt file, the Windows operating system automatically appends the specified MS-DOS subsystem search path every time you log on to your computer. Cmd.exe не использует файл AUTOEXEC. NT. Cmd.exe does not use the Autoexec.nt file. При запуске из ярлыка Cmd.exe наследует переменные среды, заданные в Мой компьютер/свойствах/дополнительном/окружении. When started from a shortcut, Cmd.exe inherits the environment variables set in My Computer/Properties/Advanced/Environment.
Примеры Examples
Для поиска по путям к:\усер\таксес, б:\усер\инвест и б:\бин для внешних команд введите: To search the paths c:\user\taxes, b:\user\invest, and b:\bin for external commands, type:
Executable search path windows
Display or set a search path for executable files at the command line.
PATH without parameters will display the current path.
The %PATH% environment variable contains a list of folders. When a command is issued at the CMD prompt, the operating system will first look for an executable file in the current folder, if not found it will scan %PATH% to find it.
Use the PATH command to display or change the list of folders stored in the %PATH% environment variable
The PATH environment variable doesn’t use spaces to separate directories. It uses semicolons: ;
You do not need to surround each part of the path with double quotes, PATH will automatically treat spaces as part of the filename.
A trailing backslash is accepted but is not required, each part of the PATH is always treated as a directory not a file.
PowerShell in particular will ignore any path node delimited by double quotes.
By default, Windows does not add a semicolon to the end of the path, but some program installers will (incorrectly) do so. This can lead to double semicolons appearing in the path list, creating a NULL node entry.
To view each item in the path on a single line use this:
Or in a batch file:
To add items to the current path, include %PATH% in your new setting:
PATH=%PATH%;C:\Program Files\My Application
Permanent Changes
Changes made using the PATH command are NOT permanent, they apply to the current CMD prompt only and remain only until the CMD window is closed.
To permanently change the PATH use Control Panel > System > Advanced System settings > Environment Variables.
The %PATH% variable is set as both a system and user variable, the 2 values are combined to give the PATH for the currently logged in user. This is explained in full by MS Product Support Article Q100843
[HKLM\System\CurrentControlSet\Control\Session Manager\Environment]
[HKCU\Environment]
Be wary of using commands like SETX to modify the PATH, the User path can be edited, but the System path remains read-only for most users. If you try to delete an old value and add a new one it is very common for the ‘delete’ to fail and the ‘add’ to succeed, resulting in duplicate values being added to the path.
To programatically modify the PATH there are a few traps to consider:
Stray quotation marks or semi-colon delimiters in the current path, Duplicate entries in the user and system paths, also duplicates in either one (Windows does not check or warn about this), the maximum length of the system path (roughly 2 KB or just 7 paths of the maximum 260 characters), and lastly checking for any dependencies in other applications (if the path you are adding or removing could be used by them).
To modify the path to add settings for a single application, one method is to use a second variable:
e.g.
SetX MYAPP «C:\Program Files\My App» -m
Now include the new variable in the path like so . C:\Windows\system32;%MYAPP%
You can now easily change that one variable %MYAPP% at any time in the future and the PATH will reflect the new value.
- Changing a variable in the Control Panel will not affect any CMD prompt that is already open, only new CMD prompts will get the new setting.
- To change a system variable you must have administrator rights
- If your system has an AUTOEXEC.BAT file then any PATH setting in AUTOEXEC.BAT will also be appended to the %PATH% environment variable. This is to provide compatibility with old installation routines which need to set the PATH. All other commands in AUTOEXEC.BAT are ignored.
PathExt
If you start/run an application without a file extension (for example WinWord instead of WinWord.exe) then the PATHEXT environment variable will be read to determine which file extensions to search for and in what order.
The default value for the PATHEXT variable is: .COM;.EXE;.BAT;.CMD
Many would argue that .CMD should have higher priority than the legacy .BAT.
Dpath
DPATH is an undocumented internal utility that allows the TYPE command to read data files in specified directories as if they were in in the current directory. On some OS’s this is also implemented as the now deprecated APPEND command. The list of directories is held in the %DPATH% environment variable which works just like the %PATH% variable, delimited with semicolons (not quotes). Syntax: DPATH pathname [;pathname].
To type any file on the path:
C:\batch\> type win.ini
The system cannot find the file specified.
C:\batch\> dpath %path%
C:\batch\> type win.ini
Terminology — filename, path, pathname
For a file stored as:
C:\Program Files\Windows Media Player\wmplayer.exe
The Filename is:
wmplayer.exe
The File Extension is:
.exe
The Path is:
\Program Files\Windows Media Player\
The Pathname is
C:\Program Files\Windows Media Player\wmplayer.exe
(so Drive + Path + Filename = Pathname)
If a file reference uses only the filename rather than a full pathname, then that will work only if the file is in the current directory or is listed in the PATH.
Paths for GUI Windows applications
Since Windows 95, the App Paths registry subkey is available to provide a location for specific executable filenames. Populating this avoids the need for applications to modify the system PATH environment variable.
The keys can be found in the following two registry locations and full documentation of this is on docs.microsoft.com
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Paths
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths
The filename used in App Paths does not have to match the destination file.
Errorlevels
If the Path was successfully changed %ERRORLEVEL% = unchanged , typically this will be 0 but if a previous command set an errorlevel, that will be preserved (this is a bug).
If Path could not be changed %ERRORLEVEL% = 1
PATH is an internal command.
“If you do not love your job, change it. Instead of pushing paper, push ideas. Instead of sitting down, stand up and be heard. Instead of complaining, contribute. don’t get stuck in a job description” — Microsoft job advert
Modifying the “Path to executable” of a windows service
I’d like to modify the path to my application, but doing so breaks it because the service still points to the old location.
By going to Administrative Tools > Services you can open a properties dialog and view the Path to executable , but there is no way to change it.
Is there any way a user can modify the service path without having to reinstall the application ?
8 Answers 8
There is also this approach seen on SuperUser which uses the sc command line instead of modifying the registry:
Note: the space after binPath= is important. You can also query the current configuration using:
This displays output similar to:
It involves editing the registry, but service information can be found in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services . Find the service you want to redirect, locate the ImagePath subkey and change that value.
You could also do it with PowerShell:
Open Run(win+R) , type «Regedit.exe» , to open «Registry Editor», go to
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
find «Apache2.4» open the folder find the «ImagePath» in the right side, open «ImagePath» under «value Data» put the following path:
«C:\xampp\apache\bin\httpd.exe» -k runservice foe XAMPP for others point to the location where Apache is installed and inside locate the bin folder «C:(Apache installed location)\bin\httpd.exe» -k runservice
Slight modification to this @CodeMaker ‘s answer, for anyone like me who is trying to modify a MongoDB service to use authentication.
When I looked at the «Path to executable» in «Services» the executed line already contained speech marks. So I had to make minor modification to his example.
- Type Services in Windows
- Find MongoDB (or the service you want to change) and open the service, making sure to stop it.
- Make a note of the Service Name (not the display name)
- Look up and copy the «Path to executable» and copy it.
For me the path was (note the speech marks)
Finding current executable’s path without /proc/self/exe
It seems to me that Linux has it easy with /proc/self/exe. But I’d like to know if there is a convenient way to find the current application’s directory in C/C++ with cross-platform interfaces. I’ve seen some projects mucking around with argv[0], but it doesn’t seem entirely reliable.
If you ever had to support, say, Mac OS X, which doesn’t have /proc/, what would you have done? Use #ifdefs to isolate the platform-specific code (NSBundle, for example)? Or try to deduce the executable’s path from argv[0], $PATH and whatnot, risking finding bugs in edge cases?
14 Answers 14
Some OS-specific interfaces:
- Mac OS X: _NSGetExecutablePath() (man 3 dyld)
- Linux: readlink /proc/self/exe
- Solaris: getexecname()
- FreeBSD: sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1
- FreeBSD if it has procfs: readlink /proc/curproc/file (FreeBSD doesn’t have procfs by default)
- NetBSD: readlink /proc/curproc/exe
- DragonFly BSD: readlink /proc/curproc/file
- Windows: GetModuleFileName() with hModule = NULL
There are also third party libraries that can be used to get this information, such as whereami as mentioned in prideout’s answer, or if you are using Qt, QCoreApplication::applicationFilePath() as mentioned in the comments.
The portable (but less reliable) method is to use argv[0] . Although it could be set to anything by the calling program, by convention it is set to either a path name of the executable or a name that was found using $PATH .
Some shells, including bash and ksh, set the environment variable » _ » to the full path of the executable before it is executed. In that case you can use getenv(«_») to get it. However this is unreliable because not all shells do this, and it could be set to anything or be left over from a parent process which did not change it before executing your program.
| grep AT_SUN_EXECNAME . – FrankH. Jun 19 ’12 at 14:13
The use of /proc/self/exe is non-portable and unreliable. On my Ubuntu 12.04 system, you must be root to read/follow the symlink. This will make the Boost example and probably the whereami() solutions posted fail.
This post is very long but discusses the actual issues and presents code which actually works along with validation against a test suite.
The best way to find your program is to retrace the same steps the system uses. This is done by using argv[0] resolved against file system root, pwd, path environment and considering symlinks, and pathname canonicalization. This is from memory but I have done this in the past successfully and tested it in a variety of different situations. It is not guaranteed to work, but if it doesn’t you probably have much bigger problems and it is more reliable overall than any of the other methods discussed. There are situations on a Unix compatible system in which proper handling of argv[0] will not get you to your program but then you are executing in a certifiably broken environment. It is also fairly portable to all Unix derived systems since around 1970 and even some non-Unix derived systems as it basically relies on libc() standard functionality and standard command line functionality. It should work on Linux (all versions), Android, Chrome OS, Minix, original Bell Labs Unix, FreeBSD, NetBSD, OpenBSD, BSD x.x, SunOS, Solaris, SYSV, HP-UX, Concentrix, SCO, Darwin, AIX, OS X, NeXTSTEP, etc. And with a little modification probably VMS, VM/CMS, DOS/Windows, ReactOS, OS/2, etc. If a program was launched directly from a GUI environment, it should have set argv[0] to an absolute path.
Understand that almost every shell on every Unix compatible operating system that has ever been released basically finds programs the same way and sets up the operating environment almost the same way (with some optional extras). And any other program that launches a program is expected to create the same environment (argv, environment strings, etc.) for that program as if it were run from a shell, with some optional extras. A program or user can setup an environment that deviates from this convention for other subordinate programs that it launches but if it does, this is a bug and the program has no reasonable expectation that the subordinate program or its subordinates will function correctly.
Possible values of argv[0] include:
- /path/to/executable — absolute path
- ../bin/executable — relative to pwd
- bin/executable — relative to pwd
- ./foo — relative to pwd
- executable — basename, find in path
- bin//executable — relative to pwd, non-canonical
- src/../bin/executable — relative to pwd, non-canonical, backtracking
- bin/./echoargc — relative to pwd, non-canonical
Values you should not see:
/bin/executable — rewritten before your program runs.
user/bin/executable — rewritten before your program runs
In addition, these may contain non-canonical path names and multiple layers of symbolic links. In some cases, there may be multiple hard links to the same program. For example, /bin/ls , /bin/ps , /bin/chmod , /bin/rm , etc. may be hard links to /bin/busybox .
To find yourself, follow the steps below:
Save pwd, PATH, and argv[0] on entry to your program (or initialization of your library) as they may change later.
Optional: particularly for non-Unix systems, separate out but don’t discard the pathname host/user/drive prefix part, if present; the part which often precedes a colon or follows an initial «//».
If argv[0] is an absolute path, use that as a starting point. An absolute path probably starts with «/» but on some non-Unix systems it might start with «» or a drive letter or name prefix followed by a colon.
Else if argv[0] is a relative path (contains «/» or «» but doesn’t start with it, such as «../../bin/foo», then combine pwd+»/»+argv[0] (use present working directory from when program started, not current).
Else if argv[0] is a plain basename (no slashes), then combine it with each entry in PATH environment variable in turn and try those and use the first one which succeeds.
Optional: Else try the very platform specific /proc/self/exe , /proc/curproc/file (BSD), and (char *)getauxval(AT_EXECFN) , and dlgetname(. ) if present. You might even try these before argv[0] -based methods, if they are available and you don’t encounter permission issues. In the somewhat unlikely event (when you consider all versions of all systems) that they are present and don’t fail, they might be more authoritative.
Optional: check for a path name passed in using a command line parameter.
Optional: check for a pathname in the environment explicitly passed in by your wrapper script, if any.
Optional: As a last resort try environment variable «_». It might point to a different program entirely, such as the users shell.
Resolve symlinks, there may be multiple layers. There is the possibility of infinite loops, though if they exist your program probably won’t get invoked.
Canonicalize filename by resolving substrings like «/foo/../bar/» to «/bar/». Note this may potentially change the meaning if you cross a network mount point, so canonization is not always a good thing. On a network server, «..» in symlink may be used to traverse a path to another file in the server context instead of on the client. In this case, you probably want the client context so canonicalization is ok. Also convert patterns like «/./» to «/» and «//» to «/». In shell, readlink —canonicalize will resolve multiple symlinks and canonicalize name. Chase may do similar but isn’t installed. realpath() or canonicalize_file_name() , if present, may help.
If realpath() doesn’t exist at compile time, you might borrow a copy from a permissively licensed library distribution, and compile it in yourself rather than reinventing the wheel. Fix the potential buffer overflow (pass in sizeof output buffer, think strncpy() vs strcpy()) if you will be using a buffer less than PATH_MAX. It may be easier just to use a renamed private copy rather than testing if it exists. Permissive license copy from android/darwin/bsd: https://android.googlesource.com/platform/bionic/+/f077784/libc/upstream-freebsd/lib/libc/stdlib/realpath.c
Be aware that multiple attempts may be successful or partially successful and they might not all point to the same executable, so consider verifying your executable; however, you may not have read permission — if you can’t read it, don’t treat that as a failure. Or verify something in proximity to your executable such as the «../lib/» directory you are trying to find. You may have multiple versions, packaged and locally compiled versions, local and network versions, and local and USB-drive portable versions, etc. and there is a small possibility that you might get two incompatible results from different methods of locating. And «_» may simply point to the wrong program.
A program using execve can deliberately set argv[0] to be incompatible with the actual path used to load the program and corrupt PATH, «_», pwd, etc. though there isn’t generally much reason to do so; but this could have security implications if you have vulnerable code that ignores the fact that your execution environment can be changed in variety of ways including, but not limited, to this one (chroot, fuse filesystem, hard links, etc.) It is possible for shell commands to set PATH but fail to export it.
You don’t necessarily need to code for non-Unix systems but it would be a good idea to be aware of some of the peculiarities so you can write the code in such a way that it isn’t as hard for someone to port later. Be aware that some systems (DEC VMS, DOS, URLs, etc.) might have drive names or other prefixes which end with a colon such as «C:», «sys$drive:[foo]bar», and «file:///foo/bar/baz». Old DEC VMS systems use «[» and «]» to enclose the directory portion of the path though this may have changed if your program is compiled in a POSIX environment. Some systems, such as VMS, may have a file version (separated by a semicolon at the end). Some systems use two consecutive slashes as in «//drive/path/to/file» or «user@host:/path/to/file» (scp command) or «file://hostname/path/to/file» (URL). In some cases (DOS and Windows), PATH might have different separator characters — «;» vs «:» and «» vs «/» for a path separator. In csh/tsh there is «path» (delimited with spaces) and «PATH» delimited with colons but your program should receive PATH so you don’t need to worry about path. DOS and some other systems can have relative paths that start with a drive prefix. C:foo.exe refers to foo.exe in the current directory on drive C, so you do need to lookup current directory on C: and use that for pwd.
An example of symlinks and wrappers on my system:
Note that user bill posted a link above to a program at HP that handles the three basic cases of argv[0] . It needs some changes, though:
- It will be necessary to rewrite all the strcat() and strcpy() to use strncat() and strncpy() . Even though the variables are declared of length PATHMAX, an input value of length PATHMAX-1 plus the length of concatenated strings is > PATHMAX and an input value of length PATHMAX would be unterminated.
- It needs to be rewritten as a library function, rather than just to print out results.
- It fails to canonicalize names (use the realpath code I linked to above)
- It fails to resolve symbolic links (use the realpath code)
So, if you combine both the HP code and the realpath code and fix both to be resistant to buffer overflows, then you should have something which can properly interpret argv[0] .
The following illustrates actual values of argv[0] for various ways of invoking the same program on Ubuntu 12.04. And yes, the program was accidentally named echoargc instead of echoargv. This was done using a script for clean copying but doing it manually in shell gets same results (except aliases don’t work in script unless you explicitly enable them).
These examples illustrate that the techniques described in this post should work in a wide range of circumstances and why some of the steps are necessary.
EDIT: Now, the program that prints argv[0] has been updated to actually find itself.
And here is the output which demonstrates that in every one of the previous tests it actually did find itself.
The two GUI launches described above also correctly find the program.
There is one potential pitfall. The access() function drops permissions if the program is setuid before testing. If there is a situation where the program can be found as an elevated user but not as a regular user, then there might be a situation where these tests would fail, although it is unlikely the program could actually be executed under those circumstances. One could use euidaccess() instead. It is possible, however, that it might find an inaccessable program earlier on path than the actual user could.