2011-05-24 63 views
1

如何获取文件或目录的长路径?在批处理脚本中,如何获取文件的长名称?

我需要一个临时目录的路径,其中没有~

%TEMP%解析C:\Users\YKAGAN~1\AppData\Local\Temp

如何获得C:\Users\ykaganovich\AppData\Local\Temp

+0

什么版本的Windows? – 2011-05-24 00:04:57

+0

Windows XP及更高版本。 – ykaganovich 2011-05-24 00:07:41

+0

理论上,我认为rundll32应该能够处理它(使用GetLongPathName入口点,无论它在哪个DLL中 - 我已经使用它,但从来不需要知道它是否是kernel32或shell32或其他)。 – 2011-05-24 13:48:31

回答

1

尝试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; 
} 
+0

谢谢!我更喜欢批量的解决方案,但我会牢记这一点......此外,它是否适用于所有64位Windows(XP,Vista,7)?我认为'Wow64DisableWow64FsRedirection'不能在32位操作系统上工作?(是的,我意识到在32位操作系统上没有'Program Files(x86)',但是目前我的脚本并不关心操作系统;它只是在所有可能的已知位置查找文件, 。 – ykaganovich 2011-05-24 00:57:04

+0

@ykaganovich:它将在32位系统上为您提供正确的结果,并在64位系统上为您提供64位结果。它不会*在64位系统上重定向(因为我使用'Wow64DisableWow64FsRedirection'),即使它是由32位命令提示符调用的,所以要小心。在32位系统上没有问题,因为如果函数实际存在,我只调用'Wow64DisableWow64FsRedirection'。 – Mehrdad 2011-05-24 01:01:12

+0

@ykaganovich:我也发布了一个C版本,但最初并没有使用它,因为我的编译器似乎使得可执行文件变得臃肿,引用了其他函数和DLL,引入了更多的依赖关系而不是必需的;如果你想要一个原生的64位版本,你需要编译C版本。 – Mehrdad 2011-05-24 01:19:25

1

编辑:

这是一个非常贪婪的方式做到这一点,但它的工作原理:

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中测试了这个功能,并在两者上都能正常工作。需要一段时间才能运行,但最终会完成工作。

+0

这就是......贪婪:) – ykaganovich 2011-05-24 17:16:49

+0

你为什么要迭代'dir'的输出而不是直接使用'for/r/d'的任何特殊原因? – Joey 2011-05-24 20:25:29

+0

@Joey;好主意,我没有想到这一点。我习惯于用'/ f'来使用'for'我总是忘记使用'/ r/d'。 – 2011-05-25 11:29:10

相关问题