用WHERE命令可以在命令行搜索文件

文章目录

用WHERE命令可以在命令行搜索文件

概述

想确认PATH变量中是否存在某个指定的程序(具体是在PATH环境变量中给出的哪个路径底下?).

开始不知道windows有where这个命令, 还自己花了2个小时写了一个小程序.

后来翻到一个cmake.bat, 才发现, 人家使用WHERE命令直接来搜索一个程序是否存在.

看了一下WHERE命令的帮助, 功能真全啊.

WHERE命令默认是在当前目录和PATH环境变量中搜索, 也可以指定路径来搜索, 还支持通配符.

where命令在winxp中没有, 在win7/win10中都有这个命令

bash 复制代码
C:\Users\chenx>where /?

WHERE [/R dir] [/Q] [/F] [/T] pattern...

描述:
    显示符合搜索模式的文件位置。在默认情况下,搜索是在当前目录和 PATH
    环境变量指定的路径中执行的。

参数列表:
    /R       从指定目录开始,递归性搜索并显示符合指定模式的文件。

    /Q       只返回退出代码,不显示匹配文件列表。(安静模式)

             匹配文件。(安静模式)

    /F       显示所有相配文件并用双引号括上。

    /T       显示所有相配文件的文件的文件。

    pattern  指定要匹配的文件的搜索模式。通配符 * 和 ? 可以用在模式中。
             也可以指定 "$env:pattern" 和 "path:pattern" 格式; 其中
             "env" 是环境变量,搜索是在 "env" 变量的指定的路径中执行的。
             这些格式不应该跟 /R 一起使用。此搜索也可以用将 PATHEXT 变
             量扩展名附加于此模式的方式完成。

     /?      显示此帮助消息。

  注意: 如果搜索成功,此工具返回错误级别 0; 如果不成功,返回 1; 如果失
        败或发生错误,返回 2。

示例:
    WHERE /?
    WHERE myfilename1 myfile????.*
    WHERE $windir:*.*
    WHERE /R c:\windows *.exe *.dll *.bat
    WHERE /Q ??.???
    WHERE "c:\windows;c:\windows\system32:*.dll"
    WHERE /F /T *.dll

笔记

没用的小程序

刚开始, 自己不知道, 写了一个小程序. 从PATH环境变量中搜索指定的程序是否存在.

比MS家提供的WHERE命令low太多了.

虽然做了一个没用的实验, 也留着以后看.

通过实验, 有以下收获.

  • _access()支持带空格的路径
c 复制代码
// getExePathNameFromEnvPath.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <map>

typedef std::map<int, const char*> MAP_ENV;

bool processEnvPath(const char* pszEnvPath, MAP_ENV& map_env, bool dispDebugInfo);
bool processPathValue(int sn, const char* pszPath, MAP_ENV& map_env, bool dispDebugInfo);
bool ReplaceEnv(const char* pszSrc, char*& pszDst, int& lenDst); // 需要调用者自己释放pszDst
bool IsFileExist(char* pszPathName);


/*! 
cmd line = THE_EXE cmake.exe cmake.cmd cmake.bat cmake.com
run result
[49] - error : %JAVA_HOME%\bin
find EXE from PATH [1] - C:\CMake\bin\cmake.exe
find EXE from PATH [2] - C:\Program Files (x86)\IncrediBuild\cmake.bat
*/

/*
正好翻到一个cmake.bat, 里面用where来检测cmake在哪里, win10中可用
where cmake
C:\CMake\bin\cmake.exe

// 默认是在当前路径和%PATH%中查找, 可以带通配符
C:\Users\chenx>where cmake.*
C:\CMake\bin\cmake.exe
C:\Program Files (x86)\IncrediBuild\cmake.txt

// 可以在指定目录下搜索指定的文件
WHERE /R c:\windows *.exe *.dll *.bat

// where 命令帮助给出的例子
	WHERE myfilename1 myfile????.*
	WHERE $windir:*.*
	WHERE /R c:\windows *.exe *.dll *.bat
	WHERE /Q ??.???
	WHERE "c:\windows;c:\windows\system32:*.dll"
	WHERE /F /T *.dll
*/

/*!
去winxp下看了一下, 并没有where这个命令
在win7/win10中都有这个命令
在win10中的位置如下:
C:\Users\chenx>where where*.*
C:\Windows\System32\where.exe
*/

int main(int argc, char** argv)
{
	MAP_ENV map_env;
	MAP_ENV::iterator it;
	int i = 0;
	const char* pszEnvPath = ::getenv("PATH");
	char szBuf[_MAX_PATH];
	int iFindPos = 0;

	do {
		if (argc < 2)
		{
			printf("function : to find argv[x]'s prog on %%PATH%%\n");
			printf("usage : THE_EXE prog_to_find1 prog_to_find2 ...\n");
			break;
		}

		// insert %path%'s value item to map
		processEnvPath(pszEnvPath, map_env, false);

		// use map_env
		for (i = 1; i < argc; i++)
		{
			for (it = map_env.begin(); it != map_env.end(); it++)
			{
				assert(NULL != it->second);
				memset(szBuf, 0, sizeof(szBuf));
				strcpy(szBuf, it->second);
				if (szBuf[strlen(szBuf) - 1] != '\\')
				{
					szBuf[strlen(szBuf)] = '\\';
				}
				strcat(szBuf, argv[i]);

				// find szBuf is exist?
				if (IsFileExist(szBuf))
				{
					printf("find EXE from PATH [%d] - %s\n", ++iFindPos, szBuf);
				}
			}
		}

		// free map_env
		for (it = map_env.begin(); it != map_env.end(); it++)
		{
			if (NULL != it->second)
			{
				delete[] it->second;
				it->second = NULL;
			}
		}

		map_env.clear();
	} while (false);

	system("pause");
}

bool IsFileExist(char* pszPathName)
{
	bool b_rc = false;

	// find EXE from PATH [2] - C:\Program Files (x86)\IncrediBuild\cmake.bat
	// _access 支持带空格的路径

	do {
		assert(NULL != pszPathName);

		if (0 != _access(pszPathName, 0))
		{
			break;
		}

		b_rc = true;
	} while (false);

	return b_rc;
}

bool processEnvPath(const char* pszEnvPath, MAP_ENV& map_env, bool dispDebugInfo)
{
	bool b_rc = false;
	char* pszBuf = NULL;
	char* pszFind = NULL;
	char* pszFindRc = NULL;
	int len = 0;
	int i = 0;

	do {
		if (NULL == pszEnvPath)
		{
			break;
		}

		len = (int)strlen(pszEnvPath);
		if (len <= 0)
		{
			break;
		}

		pszBuf = new char[len + 1];
		pszBuf[len] = '\0';
		strcpy(pszBuf, pszEnvPath);

		pszFind = pszBuf;
		do {
			i++;
			// printf("i = %d\n", i);
			if (67 == i)
			{
				i = i; // for debug
			}

			pszFindRc = strchr(pszFind, ';');
			if (NULL == pszFindRc)
			{
				// 最后一个
				processPathValue(i, pszFind, map_env, dispDebugInfo);
				break;
			}
			else {
				pszFindRc[0] = 0x00;
				processPathValue(i, pszFind, map_env, dispDebugInfo);
				pszFindRc[0] = ';';
				if (0x00 == pszFindRc[1])
				{
					break;
				}

				pszFind = pszFindRc + 1;
			}
		} while (true);
	} while (false);

	if (NULL != pszBuf)
	{
		delete[] pszBuf;
		pszBuf = NULL;
	}

	return b_rc;
}

bool processPathValue(int sn, const char* pszPath, MAP_ENV& map_env, bool dispDebugInfo)
{
	bool b_rc = false;
	char* pszTmp = NULL;
	int lenTmp = 0;

	do {
		if (NULL == pszPath)
		{
			break;
		}

		if (dispDebugInfo)
		{
			printf("[%d] %s\n", sn, pszPath);
		}

		if (NULL == strchr(pszPath, '%'))
		{
			// printf("[%2d] - %s\n", sn, pszPath);
			if (map_env.find(sn) == map_env.end())
			{
				pszTmp = new char[strlen(pszPath) + 1];
				strcpy(pszTmp, pszPath);
				map_env.insert(std::pair<int, const char*>(sn, pszTmp));
			}
			else {
				assert(false);
			}
		}
		else {
			// 有环境变量
			if (ReplaceEnv(pszPath, pszTmp, lenTmp))
			{
				// printf("[%2d] - %s\n", sn, pszPath);
				if (map_env.find(sn) == map_env.end())
				{
					map_env.insert(std::pair<int, const char*>(sn, pszTmp));
				}
				else {
					assert(false);
				}
			}
			else {
				printf("[%2d] - error : %s\n", sn, pszPath);
			}
		}

		b_rc = true;
	} while (false);

	assert(true == b_rc);
	return b_rc;
}

bool ReplaceEnv(const char* pszSrc, char*& pszDst, int& lenDst)
{
	bool b_rc = false;
	const char* pszCur = NULL;
	int iPosDst = 0;
	bool bFindEnvBegin = false;
	bool bFindEnvEnd = false;
	char szEnv[_MAX_PATH];
	int iPosEnv = 0;
	char* pszEnvValue = NULL;

	pszDst = NULL;
	lenDst = 0;
	do {
		if ((NULL == pszSrc) || (strlen(pszSrc) <= 0))
		{
			break;
		}

		pszDst = new char[_MAX_PATH];
		lenDst = _MAX_PATH;
		pszCur = pszSrc;

		while (0x00 != pszCur[0])
		{
			if (!bFindEnvBegin)
			{
				if (pszCur[0] != '%')
				{
					pszDst[iPosDst++] = pszCur[0];
				}
				else {
					bFindEnvBegin = true;
					memset(szEnv, 0, sizeof(szEnv));
					pszCur++;
					continue;
				}
			}
			else if (bFindEnvBegin && !bFindEnvEnd)
			{
				if (pszCur[0] != '%')
				{
					szEnv[iPosEnv++] = pszCur[0];
				}
				else {
					bFindEnvEnd = true;
					// get %szEnv% value pEnv
					pszEnvValue = getenv(szEnv);
					if (NULL == pszEnvValue)
					{
						goto END;
					}

					// append pEnv to pszDst
					strcpy(pszDst, szEnv);
				}

			}

			pszCur++;
		}

		b_rc = true;
	} while (false);

END:
	if (!b_rc)
	{
		if (NULL != pszDst)
		{
			delete[] pszDst;
			pszDst = NULL;
		}

		lenDst = 0;
	}

	return b_rc;
}

END

相关推荐
一丝晨光13 小时前
不同语言的注释和数组
java·开发语言·javascript·c++·c·注释·数组
想躺平的做题家1 天前
Linux高级编程_27_系统调用
linux·c
冷白白2 天前
【C++】单例模式
开发语言·c++·单例模式·c
笑非不退2 天前
VSCode 中配置 C/C++ 环境的步骤
c++·c
一丝晨光3 天前
void类型
java·开发语言·javascript·c++·c#·go·c
萧鼎3 天前
C++ 游戏开发
c++·c
湖光秋色4 天前
Linux中find命令详解
linux·gnu·find
Java Fans5 天前
macOS 开发环境配置与应用开发
macos·c
fuluoce6 天前
BACnet协议-(基于ISO 8802-3 UDP)(2)
bacnet·udp·c·智能楼宇
想躺平的做题家6 天前
Linux高级编程_26_shell
linux·运维·服务器·c