在批处理脚本中,如何获取文件的长名称?

时间:2011-05-24 00:00:06

标签: windows batch-file dos

如何获取文件或目录的长路径?

我需要一个没有~的临时目录的路径。

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

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

2 个答案:

答案 0 :(得分:1)

尝试this program我刚才写的。

来源(D):

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;
}

答案 1 :(得分:1)

编辑:按照Joey的建议使用for /r /d更新了解决方案:

这是一种相当贪婪的方法,但它有效:

pushd c:\

for /r /d %%D in (.) do (
    if /i %%~sD equ %TMP% (
        @echo %%~dpfD
        popd
        exit /b
    )
)
  • 首先pushd c:\使c:\成为搜索的起点。

  • for /r /d (.)将遍历目录树。

  • 我们遍历目录列表,将短名称(%%~sD)与变量TMP中的名称进行比较。如果它们相等,我们打印出扩展的长名称,恢复原始工作目录,然后退出脚本。

  • 需要使用%%dpfD而不是%%D;出于某种原因,%%D已将\.添加到路径名称的末尾。

  • 我最初尝试使用if %%~sD==%TMP%,但它没有用。

我在WindowsXP和Windows 7中对此进行了测试,并在两者上都有效。需要一段时间才能运行,但最终还是完成了工作。