12

我有一个不错的控制台文件管理器(Senh Liu 的 eXtreme),它将短路径/文件名作为变量传递给 menu.bat。

如何生成完整的文件夹名称+长文件名?

例子:

  • 输入变量 = "P:\MYPROG~1\SHELLS\ZBACKUP\REFSTO~1.BAL"
  • 目标变量 = "P:\MyPrograms\SHELLS\zBackup\RefsToMyData.bal"

我尝试了以下方法:

  • SET my_file=%~2

    echo %my_file%产生:"P:\MYPROG~1\SHELLS\ZBACKUP\REFSTO~1.BAL"

  • FOR /F "tokens=* USEBACKQ" %%F IN (`dir /B %2`) DO SET my_file=%%~fF

    echo %my_file%产生:"P:\MYPROG~1\SHELLS\zBackup\RefsToMyData.bal"

  • FOR /F "tokens=* USEBACKQ" %%F IN (`dir /B %2`) DO SET my_file=%%~dpnxF

    echo %my_file%产生:"P:\MYPROG~1\SHELLS\zBackup\RefsToMyData.bal"

4

10 回答 10

7

简单的解决方案:使用 PowerShell。

PS C:\> (Get-Item 'P:\MYPROG~1\SHELLS\ZBACKUP\REFSTO~1.BAL').FullName
P:\MyPrograms\SHELLS\zBackup\RefsToMyData.bal

您可以将 PowerShell 调用合并到批处理文件中,如下所示:

@echo off

setlocal

for /f "usebackq delims=" %%f in (
  `powershell.exe -Command "(Get-Item '%~1').FullName"`
) do @set "var=%%~f"

echo %var%

输出:

C:\> test.cmd P:\MYPROG~1\SHELLS\ZBACKUP\REFSTO~1.BAL
P:\MyPrograms\SHELLS\zBackup\RefsToMyData.bal

PowerShell 适用于所有受支持的 Windows 版本:

  • Windows XP SP3 和 Server 2003 SP2:PowerShell v2可用
  • Windows Vista 和 Server 2008:附带 PowerShell v1(默认未安装),提供PowerShell v2
  • Windows 7 和 Server 2008 R2:预装 PowerShell v2,提供PowerShell v3 (不含电池
  • Windows 8 和 Server 2012:预装 PowerShell v3

如果由于某种原因(例如管理限制)不能使用 PowerShell,我会改用 VBScript:

name = WScript.Arguments(0)

Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(name) Then
  Set f = fso.GetFile(name)
ElseIf fso.FolderExists(name) Then
  Set f = fso.GetFolder(name)
  If f.IsRootFolder Then
    WScript.Echo f.Path
    WScript.Quit 0
  End If
Else
  'path doesn't exist
  WScript.Quit 1
End If

Set app = CreateObject("Shell.Application")
WScript.Echo app.NameSpace(f.ParentFolder.Path).ParseName(f.Name).Path

像上面这样的 VBScript 可以在这样的批处理文件中使用:

@echo off & setlocal

for /f "delims=" %%f in ('cscript //NoLogo script.vbs "%~1"') do @set "var=%%~f"

echo %var%

不过,这确实需要一个额外的脚本文件。

于 2013-09-06T12:52:11.643 回答
5

以下应该适用于任何有效路径,只要它不是UNC 路径。路径可以是绝对的或相对的。它可以使用短文件名或长名称(或混合名称)。路径可以指文件夹或文件。

如果它是一个文件夹,结果将以结束,\如果它是一个文件,则以 no\结束。

:getLongPath例程需要一个 inputPath 变量名称作为第一个参数,以及一个可选的返回变量名称作为第二个参数。inputPath 变量应包含有效路径。如果未指定返回变量,则将结果回显到屏幕(用引号括起来)。如果指定了返回变量,则在变量中返回结果(不带引号)。

如果要返回变量,则仅在禁用延迟扩展时才应调用该例程。!如果在启用延迟扩展的情况下调用,则如果结果包含该字符,则结果将被破坏。

测试用例(仅适用于我的机器)位于脚本的顶部,实际的例程位于底部。

@echo off
setlocal
for %%F in (

  "D:\test\AB2761~1\AZCFE4~1.TXT"
  "AB2761~1\AZCFE4~1.TXT"
  "D:\test\AB2761~1\ZZCE57~1\"
  "D:\test\a b\a z.txt"
  "D:\test\a b\z z"
  "."
  "\"
  "x%%&BAN~1\test"
  "x%% & bang!\test"

) do (
  echo(
  echo resolving %%F
  set "shortPath=%%~F"
  call :getLongPath shortPath longPath
  set longPath
)

echo(
echo(
set "shortPath=D:\test\AB2761~1\AZCFE4~1.TXT"
set shortPath
echo Calling :getLongPath with with no return variable
call :getLongPath shortPath

exit /b

:getLongPath  path  [rtnVar]
setlocal disableDelayedExpansion
setlocal enableDelayedExpansion
for %%F in ("!%~1!") do (
  endlocal
  set "sourcePath=%%~sF"
  set "sourceFile=%%~nxF"
)
if not exist "%sourcePath%" (
  >&2 echo ERROR: Invalid path
  exit /b 1
)
set "rtn="
2>nul cd "%sourcePath%" || (
  cd "%sourcePath%\.."
  for /f "eol=: delims=" %%F in ('dir /b /a-d "%sourceFile%"') do set "rtn=%%F"
)
:resolveFolders
for %%F in ("%cd%") do (
  cd ..
  set "folder=%%~nxF"
)
if defined folder for /f "eol=: delims=" %%: in ('dir /b /ad') do (
  if /i "%%~snx:" equ "%folder%" (
    set "rtn=%%:\%rtn%"
    goto :resolveFolders
  )
)
set "rtn=%cd%%rtn%
( endlocal
  if "%~2" equ "" (echo "%rtn%") else set "%~2=%rtn%"
)

=== 输出 ===

resolving "D:\test\AB2761~1\AZCFE4~1.TXT"
longPath=D:\test\a b\a z.txt

resolving "AB2761~1\AZCFE4~1.TXT"
longPath=D:\test\a b\a z.txt

resolving "D:\test\AB2761~1\ZZCE57~1\"
longPath=D:\test\a b\z z\

resolving "D:\test\a b\a z.txt"
longPath=D:\test\a b\a z.txt

resolving "D:\test\a b\z z"
longPath=D:\test\a b\z z\

resolving "."
longPath=D:\test\

resolving "\"
longPath=D:\

resolving "x%&BAN~1\test"
longPath=D:\test\x% & bang!\test\

resolving "x% & bang!\test"
longPath=D:\test\x% & bang!\test\


shortPath=D:\test\AB2761~1\AZCFE4~1.TXT
Calling :getLongPath with with no return variable
"D:\test\a b\a z.txt"

如果你想运行上面的代码,那么我建议你完全删除 和 之间的所有测试场景@echo off代码:getLongPath。然后您可以简单地调用脚本,将任何有效路径作为第一个参数传递。结果应该打印出正确的长路径。

我很惊讶使用批处理来解决这个问题有多么困难。我认为使用 JScript 或 VBS 并不容易(实际上,Ansgar 找到了一个不错的 VBS 解决方案)。但我喜欢 Ansgar 的简单 PowerShell 解决方案——简单多了。


更新

我发现了一个模糊的情况,如果从 FOR 循环中调用上述代码会失败,并且路径中恰好有 FOR 变量。它也不会正确地将带有通配符的路径报告为错误,并且当路径包含!.

所以我在下面创建了一个修改版本。我非常有信心它应该真正适用于所有情况,除了 UNC 路径,并且路径中可能没有 unicode。我将它打包为一个易于调用的过程,并附带内置文档。它可以作为独立脚本保留,也可以合并到更大的脚本中。

@echo off
:getLongPath
:::
:::getLongPath  PathVar  [RtnVar]
:::getLongPath  /?
:::
:::  Resolves the path contained in PathVar into the full long path.
:::  If the path represents a folder then it will end with \
:::
:::  The result is returned in variable RtnVar.
:::  The result is echoed to the screen if RtnVar is not specified.
:::
:::  Prints this documentation if the first argument is /?

if "%~1" equ "" (
  >&2 echo ERROR: Insufficient arguments. Use getLongPath /? to get help.
  exit /b 1
)
if "%~1" equ "/?" (
  for /f "delims=" %%A in ('findstr "^:::" "%~f0"') do (
    set "ln=%%A"
    setlocal enableDelayedExpansion
    echo(!ln:~3!
    endlocal
  )
  exit /b 0
)
setlocal
set "notDelayed=!"
setlocal disableDelayedExpansion
setlocal enableDelayedExpansion
for /f "eol=: delims=" %%F in ("!%~1!") do (
  endlocal
  set "sourcePath=%%~sF"
  set "sourcePath2=%%F"
  set "sourceFile=%%~nxF"
)
if not exist "%sourcePath%" (
  >&2 echo ERROR: Invalid path
  exit /b 1
)
set "sourcePath3=%sourcePath2:**=%"
set "sourcePath3=%sourcePath3:?=%"
if "%sourcePath3%" neq "%sourcePath2%" (
  >&2 echo ERROR: Invalid path
  exit /b 1
)
set "rtn="
2>nul cd "%sourcePath%" || (
  cd "%sourcePath%\.."
  for /f "eol=: delims=" %%F in ('dir /b /a-d "%sourceFile%"') do set "rtn=%%F"
)
:resolveFolders
for %%F in ("%cd%") do (
  cd ..
  set "folder=%%~nxF"
)
if defined folder for /f "delims=: tokens=1,2" %%A in ("%folder%:%rtn%") do for /f "eol=: delims=" %%F in ('dir /b /ad') do (
  if /i "%%~snxF" equ "%%A" (
    set "rtn=%%F\%%B"
    goto :resolveFolders
  )
)
set "rtn=%cd%%rtn%"
if not defined notDelayed set "rtn=%rtn:^=^^%"
if not defined notDelayed set "rtn=%rtn:!=^!%"
if not defined notDelayed (set "!=!==!") else set "!="
for %%A in ("%rtn%") do (
  endlocal
  endlocal
  if "%~2" equ "" (echo %%~A%!%) else set "%~2=%%~A"!
)

我还将 Ansgar 的 VBS 改编为混合 JScript/批处理脚本。它应该提供与上述纯批处理脚本相同的结果,但 JScript 更易于遵循。

@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScrpt comment
@echo off

:getLongpath
:::
:::getLongPath  PathVar  [RtnVar]
:::getLongPath  /?
:::
:::  Resolves the path contained in PathVar into the full long path.
:::  If the path represents a folder then it will end with \
:::
:::  The result is returned in variable RtnVar.
:::  The result is echoed to the screen if RtnVar is not specified.
:::
:::  Prints this documentation if the first argument is /?

::************ Batch portion ***********
if "%~1" equ "" (
  >&2 echo ERROR: Insufficient arguments. Use getLongPath /? to get help.
  exit /b 1
)
if "%~1" equ "/?" (
  for /f "delims=" %%A in ('findstr "^:::" "%~f0"') do (
    set "ln=%%A"
    setlocal enableDelayedExpansion
    echo(!ln:~3!
    endlocal
  )
  exit /b 0
)
setlocal
set "notDelayed=!"
setlocal disableDelayedExpansion
set "rtn="
for /f "delims=" %%A in ('cscript //E:JScript //nologo "%~f0" %*') do set "rtn=%%A"
if not defined rtn exit /b 1
if not defined notDelayed set "rtn=%rtn:^=^^%"
if not defined notDelayed set "rtn=%rtn:!=^!%"
if not defined notDelayed (set "!=!==!") else set "!="
for %%A in ("%rtn%") do (
  endlocal
  endlocal
  if "%~2" equ "" (echo %%~A%!%) else set "%~2=%%~A"!
)
exit /b 0

************ JScript portion ***********/
var env=WScript.CreateObject("WScript.Shell").Environment("Process");
var fso=WScript.CreateObject("Scripting.FileSystemObject");
var app=WScript.CreateObject("Shell.Application");
var inPath=env(WScript.Arguments.Item(0));
var folder="";
var f;
if (fso.FileExists(inPath)) {
  f=fso.GetFile(inPath);
}
else if (fso.FolderExists(inPath)) {
  folder="\\"
  f=fso.GetFolder(inPath);
  if (f.IsRootFolder) {
    WScript.StdOut.WriteLine(f.Path);
    WScript.Quit(0);
  }
}
else {
  WScript.StdErr.WriteLine('ERROR: Invalid path');
  WScript.Quit(1);
}
WScript.StdOut.WriteLine( app.NameSpace(f.ParentFolder.Path).ParseName(f.Name).Path + folder);
于 2013-09-06T18:06:09.510 回答
3

这将返回完整的长路径名,但取决于:
A)树中没有太多文件(由于花费时间)
B)树中只有一个目标(长)文件名。

@echo off
for /f "delims=" %%a in (' dir /b "%~1" ') do set "file=%%a"
for /f "delims=~" %%a in ("%~dp1") do cd /d "%%a*"
for /f "delims=" %%a in ('dir /b /s /a-d "%file%" ') do set "var=%%a"
echo "%var%"

当用它调用mybat "d:\MYPROG~1\SHELLS\zBackup\REFSTO~1.BAL"
时返回:

"d:\MyPrograms\SHELLS\zBackup\RefsToMyData.bal"

于 2013-09-07T05:27:38.517 回答
2

还有一个出人意料的简单解决方案:

 echo lcd %some_path%|ftp

编辑显示示例:它不是 100%

d:\>echo lcd C:\Files\Download\MYMUSI~1\iTunes\ALBUMA~1 |ftp  
Local directory now C:\Files\Download\MYMUSI~1\iTunes\Album Artwork. 
于 2013-10-11T23:23:53.140 回答
1
@echo off
setlocal
rem this need to be a short name to avoid collisions with dir command bellow
cd C:\BALBAL~1\BLBALB~1\
set "curr_dir=%cd%"
set "full_path="

:repeat

for /f "delims=" %%f in ('for %%d in ^(.^) do @dir  /a:d /n /b "..\*%%~snd"') do ( 
    set "full_path=%%f\%full_path%"
)

cd ..

if ":\" NEQ "%cd:~-2%" (
    goto :repeat
) else (
    set "full_path=%cd%%full_path%"
)

echo --%full_path%--
cd %curr_dir%
endlocal

路径在开始时是硬编码的,但您可以更改它或对其进行参数化。因为您可以轻松获取文件的全名,这里只是目录的解决方案。

编辑

现在适用于文件和目录,并且可以传递参数:

   @echo off

rem ---------------------------------------------
rem ---------------------- TESTS ----------------
rem ----------------------------------------------

md "c:\test\blablablablabl\bla bla bla\no no no no no no\yes yes yes" >nul 2>&1
md "c:\test\1                      b1\1\" >nul 2>&1
for %%t in ("c:\test\blablablablabl\bla bla bla\no no no no no no\yes yes yes") do set t_dir=%%~st
for %%t in ("c:\test\1                      b1\1\") do set t_dir2=%%~st
echo a>"%t_dir2%a"
echo a>"%t_dir2%a a.txt"

echo testing "%t_dir%\\"
call :get_full_name "%t_dir%\\"
echo(
echo testing "%t_dir2%a"
call :get_full_name "%t_dir2%a"
echo(
echo testing "%t_dir2%a a.txt" with return variable
call :get_full_name  "%t_dir2%a a.txt" test_var
echo  return variable : -- %test_var% --
goto :eof

rem -------------------------------------

:get_full_name [%1 - short path to a file or directory ; %2 - if set stores the result in variable with that name] 
setlocal
if not exist "%~1" ( echo file/dir does not exist & exit /b 2 )

set "curr_dir=%cd%"
for /f "delims=" %%n  in ('dir /b /n "%~dps1\%~snx1"') do set "name=%%n"

cd "%~dps1"
set "full_path="
:repeat
for /f "delims=" %%f in ('for %%d in ^(.^) do @dir  /a:d /n /b "..\*%%~snd"') do ( 
    set "full_path=%%~f\%full_path%"
)
cd ..
if ":\" NEQ "%cd:~-2%" (
    goto :repeat
) else (
    set "full_path=%cd%%full_path%"
)

echo %full_path%%name%
cd %curr_dir%
endlocal & if "%~2" NEQ ""  set "%~2=%full_path%%name%"

和测试输出:

testing "c:\test\BLABLA~1\BLABLA~1\NONONO~1\YESYES~1\\"
c:\test\blablablablabl\bla bla bla\no no no no no no\yes yes yes\

testing "c:\test\1B1~1\1\a"
c:\test\1                      b1\1\a

testing "c:\test\1B1~1\1\a a.txt" with return variable
c:\test\1                      b1\1\a a.txt
 return variable : -- c:\test\1                      b1\1\a a.txt --
于 2013-09-06T12:32:25.687 回答
1

这是一个丑陋的批处理作业,我的代码不好,但是蛮力:-)

@echo off &SETLOCAL
SET "short=P:\MYPROG~1\SHELLS\ZBACKUP\REFSTO~1.BAL"
SET "shorty=%short:\= %"

FOR %%a IN (%short%) DO SET "shortname=%%~nxa"
FOR %%a IN (%shorty%) DO (
    IF DEFINED flag (
        CALL :doit "%%~a"
    ) ELSE (
        SET "longpath=%%~a"
        SET flag=true
        SET "first=\"
    )
)
ECHO "%longpath%"
goto:eof

:doit
SET "last=%~1"
IF "%last%" neq "%shortname%" (SET "isDir=/ad") ELSE SET "isDir=/a-d"
FOR /f "delims=" %%b IN ('dir %isdir% %longpath%%first%^|findstr /ri "\<%last%\>"') DO SET "X0=%%b"
FOR /f "delims=" %%b IN ('dir %isdir% /x %longpath%%first%^|findstr /ri "\<%last%\>"') DO SET "X1=%%b"
REM for European time format
IF "%X0: =%"=="%X1: =%" (SET /a token=3) ELSE SET /a token=4
REM for "AM/PM" time format
IF "%X0: =%"=="%X1: =%" (SET /a token=4) ELSE SET /a token=5
FOR /f "tokens=%token%*" %%b IN ('dir %isdir% /x %longpath%%first%^|findstr /ri "\<%last%\>"') DO SET "longname=%%~c"
SET "longpath=%longpath%\%longname%"
SET "first="
goto:eof

请在函数中设置您的时间格式doit(根据适用格式删除)。
这可能会因路径或文件名中的特殊字符而失败,例如!%=&^.

于 2013-09-06T16:18:25.537 回答
1

一次尝试WMICand Win32_Directory.Probably 比使用cdand慢dir,但当前目录没有改变:

@echo off
:get_full_name [%1 - short path to a file or directory ; %2 - if set stores the result in variable with that name]
setlocal 
if not exist "%~1" ( echo file/dir does not exist & exit /b 2 )
for /f "delims=" %%n  in ('dir /b /n "%~dps1\*%~snx1"') do set "name=%%n"

set "short_path=%~dps1"
set "short_path=%short_path:~0,-1%"
set "drive=%short_path:~0,2%"

set "full_name="

:repeat
set "short_path=%short_path:\=\\%"
set "short_path=%short_path:'=\'%"

FOR /F "usebackq skip=2 delims=" %%P in (`WMIC path win32_directory where name^='%short_path%'  get Path^,FileName /Format:Textvaluelist.xsl`) do  for /f "delims=" %%C in ("%%P") do (
    set "_%%C"
)
set "_Path=%_Path:~0,-1%"

set full_name=%_FileName%\%full_name%
if "%_Path%" NEQ "" (
    set "short_path=%drive%%_Path%"
    goto :repeat
) else (
    set full_name=%drive%\%_FileName%\%full_name%
)
echo %full_name%%name%
endlocal  if "%~2" NEQ ""  set "%~2=%full_path%%name%"

还没有经过重度测试......

于 2013-09-08T08:40:27.773 回答
1

这是一个基于npocmaka答案的批处理脚本,使用命令(连同其子命令)。在那里您可以看到只有路径的最后一个元素被扩展为长名称。我现在的想法是为路径的每个元素单独应用子命令,因此我们将在最终输出中获得所有元素的全名。ftplcdlcd

此脚本仅适用于目录。它不适用于文件,也不适用于 UNC 路径。

所以我们开始:

@echo off

setlocal EnableExtensions DisableDelayedExpansion

set "ARGS=%*"
set FTP_CMD=lcd
set "TEMP_FILE=%TEMP%\%~n0_%RANDOM%.tmp"

setlocal EnableDelayedExpansion
for %%A in (!ARGS!) do (
    endlocal
    set "ARG=%%~fA" & set "SEP=\"
    setlocal EnableDelayedExpansion
    > "%TEMP_FILE%" (
        for %%D in ("!ARG:\=" "!") do (
            endlocal
            if not "%%~D"=="" (
                set "ITEM=%%~D"
                setlocal EnableDelayedExpansion
                echo(%FTP_CMD% "!ITEM!!SEP!"
                endlocal
                set "SEP="
            )
            setlocal EnableDelayedExpansion
        )
    )
    set "PREFIX="
    for /F "delims=" %%L in ('^< "%TEMP_FILE%" ftp') do (
        endlocal
        if not defined PREFIX set "PREFIX=%%L"
        set "LONG_PATH=%%L"
        setlocal EnableDelayedExpansion
    )
    set "PREFIX=!PREFIX::\.=!" & set "PREFIX=!PREFIX:~,-1!"
    for /F "delims=" %%E in ("!PREFIX!") do (
        set "LONG_PATH=!LONG_PATH:*%%E=!"
        set "LONG_PATH=!LONG_PATH:~,-1!"
    )
    echo(!LONG_PATH!
)
endlocal

del /Q "%TEMP_FILE%"

endlocal
exit /B

基本上有一个for %%D循环遍历给定路径的所有元素(在它被最外面的for %%A循环扩展到其完整路径之后)。每个元素都包含在""其中并以(用于更改本地工作目录lcd的命令的子命令)开头。ftp对于构成驱动器的第一个路径元素,\会附加一个尾随以引用其根目录。这些构建的路径字符串中的每一个都被写入一个临时文件。

接下来临时文件被重定向到ftp命令中,因此它通过路径元素更改其本地工作目录路径元素。的输出ftpfor /F %%L循环捕获。实际上,输出的最后一行是有意义的,因为它包含完整的长路径。但是,第一行也被存储,其中使用了适用驱动器的根目录。只需要轻松提取输出行的前缀,以便将其从包含完整路径的输出行中删除(ftp命令输出类似于Local directory now D:\.英语系统的内容,但我希望脚本与语言无关)。最后,从完整的长路径中删除所述前缀,并在控制台上返回结果。


这是一种改进的方法,它也可以处理文件的路径,通过在这种情况下由子例程单独处理最后一个路径元素:LAST_ITEM,它不依赖于但依赖于循环将最后一个路径元素扩展为长路径ftp的事实for给出了通配符:

@echo off

setlocal EnableExtensions DisableDelayedExpansion

set "ARGS=%*"
set FTP_CMD=lcd
set "TEMP_FILE=%TEMP%\%~n0_%RANDOM%.tmp"

setlocal EnableDelayedExpansion
for %%A in (!ARGS!) do (
    endlocal
    set "ARG=%%~fA" & set "SEP=\" & set "ITEM="
    if exist "%%~fA" (
        if exist "%%~fA\" (set "FLAG=") else set "FLAG=#"
        setlocal EnableDelayedExpansion
        > "%TEMP_FILE%" (
            for %%D in ("!ARG:\=" "!") do (
                endlocal
                if not "%%~D"=="" (
                    set "ITEM=%%~D"
                    setlocal EnableDelayedExpansion
                    echo(!FTP_CMD! "!ITEM!!SEP!"
                    endlocal
                    set "SEP="
                ) else set "ITEM="
                setlocal EnableDelayedExpansion
            )
        )
        set "PREFIX="
        for /F "delims=" %%L in ('^< "%TEMP_FILE%" 2^> nul ftp') do (
            endlocal
            if not defined PREFIX set "PREFIX=%%L"
            set "LONG_PATH=%%L"
            setlocal EnableDelayedExpansion
        )
        set "PREFIX=!PREFIX::\.=!" & set "PREFIX=!PREFIX:~,-1!"
        for /F "delims=" %%E in ("!PREFIX!") do (
            set "LONG_PATH=!LONG_PATH:*%%E=!"
            set "LONG_PATH=!LONG_PATH:~,-1!"
        )
        if not "!LONG_PATH:~-2!"==":\" set "LONG_PATH=!LONG_PATH!\"
        for /F "tokens=1,2 delims=|" %%S in ("!LONG_PATH!|!ITEM!") do (
            endlocal
            set "LONG_PATH=%%S" & set "ITEM=%%T"
            if defined FLAG call :LAST_ITEM ITEM LONG_PATH
            setlocal EnableDelayedExpansion
        )
        if defined FLAG (echo(!LONG_PATH!!ITEM!) else echo(!LONG_PATH!
    ) else setlocal EnableDelayedExpansion
)
endlocal

del /Q "%TEMP_FILE%"

endlocal
exit /B


:LAST_ITEM  var_last_item  var_long_path
setlocal EnableDelayedExpansion
for %%I in ("!%~2!!%~1!*") do (
    endlocal
    set "LONG=%%~nxI" & set "SHORT=%%~snxI"
    setlocal EnableDelayedExpansion
    if /I "!LONG!"=="!%~1!" (set "%~1=!LONG!"
    ) else if /I "!SHORT!"=="!%~1!" set "%~1=!LONG!"
)
for /F "delims=" %%T in ("!%~1!") do (
    endlocal
    set "%~1=%%T"
    setlocal EnableDelayedExpansion
)
endlocal
exit /B
于 2016-05-06T17:50:47.690 回答
0

我的解决方案:

set shortname=P:\MYPROG~1\SHELLS\ZBACKUP\REFSTO~1.BAL
for /F %f in ('dir /b /s %shortname%') do where /R %~dpf %~nf%~xf

如果您在批处理文件中使用它:

for /F %%f in ('dir /b /s %shortname%') do where /R %%~dpf %%~nf%%~xf
于 2018-11-18T09:45:03.940 回答
0

好的,这是我前段时间开始的一个脚本,依赖于在使用通配符dir /B时返回长文件或目录名的事实。这是一种递归方法,它遍历作为命令行参数给出的路径的目录层次结构并解析每个元素。请注意,它在包含和/或由于使用的路径方面存在问题:%^call

@echo off
setlocal EnableExtensions DisableDelayedExpansion

set ARGS=%*
set "COLL="

setlocal EnableDelayedExpansion
for %%A in (!ARGS!) do (
    endlocal
    set "ARG=%%~fA"
    if exist "%%~fA" (
        call :PROC_ITEM COLL "%%~fA" || set "COLL="
    )
    setlocal EnableDelayedExpansion
)
if defined COLL (echo(!COLL!) else exit /B 1
endlocal

endlocal
exit /B


:PROC_ITEM  rtn_built_path  val_source_path
setlocal DisableDelayedExpansion
set "FND="
if "%~pnx2"=="\" (
    set "COLL=%~d2"
) else (
    cd /D "%~dp2." & rem (this must be set before `for /F` in order for `%%~snxJ` to refer to it!)
    for /F "delims= eol=|" %%J in ('dir /B /A "%~f2?"') do (
        if /I "%%J"=="%~nx2" (
            set "FND=\%%J" & rem (this assignment should be executed for long names)
        ) else (
            if /I "%%~snxJ"=="%~nx2" set "FND=\%%J" & rem (and this for short ones)
        )
    )
    if defined FND (
        call :PROC_ITEM COLL "%~dp2."
    ) else (
        exit /B 1 & rem (this intercept exceptions and should usually not happen)
    )
)
endlocal & set "%~1=%COLL%%FND%"
exit /B
于 2020-04-10T22:58:56.473 回答