在批处理脚本中,如何获取文件的长名称?
如何获取文件或目录的长路径?在批处理脚本中,如何获取文件的长名称?
我需要一个临时目录的路径,其中没有~
。
%TEMP%
解析C:\Users\YKAGAN~1\AppData\Local\Temp
如何获得C:\Users\ykaganovich\AppData\Local\Temp
?
尝试this program我刚刚写道。
源():
import core.stdc.wchar_, core.sys.windows.windows;
extern (C) int __wgetmainargs(out int pargc, out wchar** pargv, out wchar** penvp, int dowildcard, out int startinfo);
extern (Windows) BOOL Wow64DisableWow64FsRedirection(out void* OldValue);
extern (Windows) HMODULE LoadLibraryW(in LPCWSTR lpFileName);
extern (Windows) DWORD GetLongPathNameW(in LPCWSTR lpszShortPath, LPWSTR lpszLongPath, in DWORD cchBuffer);
pragma(startaddress, wmainCRTStartup);
pragma(lib, "msvcrt.lib");
void* disableWow64Redirection()
{
auto pKernel32 = LoadLibraryW("kernel32.dll");
void* old;
auto fn = cast(typeof(&Wow64DisableWow64FsRedirection))GetProcAddress(cast(HMODULE)pKernel32, "Wow64DisableWow64FsRedirection");
if (fn != null) { if (!fn(old)) { } }
else { old = null; }
FreeLibrary(pKernel32);
return old;
}
int wmainCRTStartup()
{
disableWow64Redirection();
int argc, si; wchar** wargv, wenvp;
__wgetmainargs(argc, wargv, wenvp, 0, si);
wchar[32 * 1024] buffer = void; //big enough for all valid paths
foreach (i; 1 .. argc)
{
auto len = GetLongPathNameW(wargv[i], buffer.ptr, buffer.length - 1);
buffer.ptr[len] = '\0';
if (i > 1) { wprintf(" "); }
wprintf("%s", len > 0 ? buffer.ptr : wargv[i]);
}
return 0;
}
用法:
name <short-name>
什么鬼,这里是一个C版本:
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
typedef BOOL (WINAPI * PWow64DisableWow64FsRedirection)(void** OldValue);
int _tmain(int argc, TCHAR *wargv[])
{
int i;
wchar_t buffer[32 * 1024]; //big enough for all valid paths
PWow64DisableWow64FsRedirection fn =
(PWow64DisableWow64FsRedirection)GetProcAddress(
GetModuleHandle(_T("kernel32.dll")), "Wow64DisableWow64FsRedirection");
if (sizeof(size_t) > 4 && fn != NULL) //Remove if WOW64 wanted
{ void* old; Wow64DisableWow64FsRedirection(&old); }
for (i = 1; i < argc; i++)
{
DWORD len = GetLongPathNameW(wargv[i], buffer, ARRAYSIZE(buffer) - 1);
buffer[len] = _T('\0');
if (i > 1) { wprintf(_T(" ")); }
wprintf(_T("%s"), len > 0 ? buffer : wargv[i]);
}
return 0;
}
谢谢!我更喜欢批量的解决方案,但我会牢记这一点......此外,它是否适用于所有64位Windows(XP,Vista,7)?我认为'Wow64DisableWow64FsRedirection'不能在32位操作系统上工作?(是的,我意识到在32位操作系统上没有'Program Files(x86)',但是目前我的脚本并不关心操作系统;它只是在所有可能的已知位置查找文件, 。 – ykaganovich 2011-05-24 00:57:04
@ykaganovich:它将在32位系统上为您提供正确的结果,并在64位系统上为您提供64位结果。它不会*在64位系统上重定向(因为我使用'Wow64DisableWow64FsRedirection'),即使它是由32位命令提示符调用的,所以要小心。在32位系统上没有问题,因为如果函数实际存在,我只调用'Wow64DisableWow64FsRedirection'。 – Mehrdad 2011-05-24 01:01:12
@ykaganovich:我也发布了一个C版本,但最初并没有使用它,因为我的编译器似乎使得可执行文件变得臃肿,引用了其他函数和DLL,引入了更多的依赖关系而不是必需的;如果你想要一个原生的64位版本,你需要编译C版本。 – Mehrdad 2011-05-24 01:19:25
编辑:
这是一个非常贪婪的方式做到这一点,但它的工作原理:
pushd c:\
for /r /d %%D in (.) do (
if /i %%~sD equ %TMP% (
@echo %%~dpfD
popd
exit /b
)
)
首先
pushd c:\
使c:\
起点使用for /r /d
的建议乔伊更新的解决方案的搜索。for /r /d (.)
将走过目录树。我们通过比较短名称(
%%~sD
)和变量TMP
中的名称的目录列表进行循环。如果它们相同,我们打印扩展的长名称,恢复原始工作目录并退出脚本。需要使用%%dpfD
而不是%%D
;出于某种原因,%%D
已将\.
添加到路径名的末尾。我一开始尝试使用
if %%~sD==%TMP%
,但它没有奏效。
我在WindowsXP和Windows 7中测试了这个功能,并在两者上都能正常工作。需要一段时间才能运行,但最终会完成工作。
这就是......贪婪:) – ykaganovich 2011-05-24 17:16:49
你为什么要迭代'dir'的输出而不是直接使用'for/r/d'的任何特殊原因? – Joey 2011-05-24 20:25:29
@Joey;好主意,我没有想到这一点。我习惯于用'/ f'来使用'for'我总是忘记使用'/ r/d'。 – 2011-05-25 11:29:10
什么版本的Windows? – 2011-05-24 00:04:57
Windows XP及更高版本。 – ykaganovich 2011-05-24 00:07:41
理论上,我认为rundll32应该能够处理它(使用GetLongPathName入口点,无论它在哪个DLL中 - 我已经使用它,但从来不需要知道它是否是kernel32或shell32或其他)。 – 2011-05-24 13:48:31