在使用Git Bash的时候经常碰到需要输入文件路径的情况,但是直接在windows下复制的文件路径bash无法正确的识别,会将\当成转义符处理,导致文件路径没有分隔符。每次都需要自己手动的修改。所以想着自己写个程序直接一键转换。
首先需要获取剪贴板的内容,借助windows api函数来完成这个功能
static std::string getClipboard()
{
if (OpenClipboard(NULL))
{
HANDLE hData = GetClipboardData(CF_TEXT);
if (hData == nullptr)
{
return std::string();
}
char *pszText = static_cast<char *>(GlobalLock(hData));
std::string text(pszText);
GlobalUnlock(hData);
CloseClipboard();
return text;
}
else
{
std::cout << "Failed to open clipboard" << std::endl;
return "";
}
}
获取剪贴板数据后,首先判断剪贴板中的内容是否是文件路径,以及返回文件路径是windows风格还是linux风格,这里借助正则表达式来完成
static int pathOrNot(const std::string &text)
{
std::regex windowsPathRegex(R"(^[a-zA-Z]?:?[\.~]?(\\)([^\\:*?"<>|\r\n]+(\\)?)*$)");
std::regex linuxPathRegex(R"(^[\.~]?/?(/[^/]+)+/?$)");
if (std::regex_match(text, windowsPathRegex))
{
return 0;
}
else if (std::regex_match(text, linuxPathRegex))
{
return 1;
}
else
{
return -1;
}
}
然后是对文件路径的处理
static void toLinuxStyle()
{
std::string text = getClipboard();
if (text.empty())
{
return;
}
if ((pathOrNot(text) == 1) || (pathOrNot(text) == -1))
{
std::cout << "No need to operate" << std::endl;
return;
}
replaceChar(text, '\\', '/');
if (text[1] == ':')
{
deleteChar(text, 1);
insertChar(text, '/', 0);
}
writeToClipboard(text);
std::cout << text << std::endl;
}
static void towindowsStyle()
{
std::string text = getClipboard();
if (text.empty())
{
return;
}
if ((pathOrNot(text) == 0) || (pathOrNot(text) == -1))
{
std::cout << "No need to operate" << std::endl;
return;
}
replaceChar(text, '/', '\\');
if (text[0] == '\\')
{
deleteChar(text, 0);
insertChar(text, ':', 1);
}
writeToClipboard(text);
std::cout << text << std::endl;
}
完整代码
#include <iostream>
#include <cstring>
#include <windows.h>
#include <regex>
#include <string>
#pragma comment(lib, "user32.lib")
static void toLinuxStyle();
static void towindowsStyle();
static void replaceChar(std::string &str, char target, char replacement);
static std::string getClipboard();
static int pathOrNot(const std::string &text);
static void deleteChar(std::string &str, int pos);
static void insertChar(std::string &str, char toInsert, int pos);
static void writeToClipboard(const std::string &text);
int main(int argc, char **argv)
{
bool mode;
if (argc < 2 || ((strcmp(argv[1], "-l") != 0) && (strcmp(argv[1], "-w") != 0)))
{
std::cout << "-w windows style\n-l linux style" << std::endl;
mode = true;
}
else
{
if (strcmp(argv[1], "-l") == 0)
{
mode = true;
}
else
{
mode = false;
}
}
if (mode)
{
toLinuxStyle();
}
else
{
towindowsStyle();
}
return 0;
}
static void toLinuxStyle()
{
std::string text = getClipboard();
if (text.empty())
{
return;
}
if ((pathOrNot(text) == 1) || (pathOrNot(text) == -1))
{
std::cout << "No need to operate" << std::endl;
return;
}
replaceChar(text, '\\', '/');
if (text[1] == ':')
{
deleteChar(text, 1);
insertChar(text, '/', 0);
}
writeToClipboard(text);
std::cout << text << std::endl;
}
static void towindowsStyle()
{
std::string text = getClipboard();
if (text.empty())
{
return;
}
if ((pathOrNot(text) == 0) || (pathOrNot(text) == -1))
{
std::cout << "No need to operate" << std::endl;
return;
}
replaceChar(text, '/', '\\');
if (text[0] == '\\')
{
deleteChar(text, 0);
insertChar(text, ':', 1);
}
writeToClipboard(text);
std::cout << text << std::endl;
}
static void replaceChar(std::string &str, char target, char replacement)
{
for (char &c : str)
{
if (c == target)
{
c = replacement;
}
}
}
static std::string getClipboard()
{
if (OpenClipboard(NULL))
{
HANDLE hData = GetClipboardData(CF_TEXT);
if (hData == nullptr)
{
return std::string();
}
char *pszText = static_cast<char *>(GlobalLock(hData));
std::string text(pszText);
GlobalUnlock(hData);
CloseClipboard();
return text;
}
else
{
std::cout << "Failed to open clipboard" << std::endl;
return "";
}
}
static int pathOrNot(const std::string &text)
{
std::regex windowsPathRegex(R"(^[a-zA-Z]?:?[\.~]?(\\)([^\\:*?"<>|\r\n]+(\\)?)*$)");
std::regex linuxPathRegex(R"(^[\.~]?/?(/[^/]+)+/?$)");
if (std::regex_match(text, windowsPathRegex))
{
return 0;
}
else if (std::regex_match(text, linuxPathRegex))
{
return 1;
}
else
{
return -1;
}
}
static void deleteChar(std::string &str, int pos)
{
if (pos < str.length())
{
str.erase(pos, 1);
}
}
static void insertChar(std::string &str, char toInsert, int pos)
{
if (pos <= str.length())
{
str.insert(pos, 1, toInsert);
}
}
static void writeToClipboard(const std::string &text)
{
if (OpenClipboard(nullptr))
{
EmptyClipboard();
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, text.size() + 1);
if (hGlob != nullptr)
{
LPVOID lpData = GlobalLock(hGlob);
if (lpData != nullptr)
{
memcpy(lpData, text.c_str(), text.size() + 1);
GlobalUnlock(hGlob);
SetClipboardData(CF_TEXT, hGlob);
}
}
CloseClipboard();
}
}
使用MSVC编译器编译
cl main.cpp -o pt
然后把pt程序复制到git bash里的/usr/bin文件夹内,测试