使用cmd.exe将长文件名转换为短文件名(8.3)

36

我试图在Windows上将长文件名转换为短文件名(8.3)。

一个带有命令行参数的批处理文件可以按预期工作:

short.bat:

@echo OFF
echo %~s1

调用short.bat C:\Documents and Settings\User\NTUSER.DAT会返回C:\DOCUM~1\USER\NTUSER.DAT

然而,我不想使用额外的.bat文件。我宁愿从ruby脚本中使用整个命令来调用cmd.exe。如何实现?

作为中间步骤,我尝试在批处理文件中硬编码路径,但这样做不起作用:

short1.bat:

@echo OFF
SET filename="C:\Documents and Settings\User\NTUSER.DAT"
echo %filename%
echo %~sfilename%

echo %filename% 可以正常运行,但是 echo %~sfilename% 会出现以下错误:

The following usage of the path operator in batch-parameter
substitution is invalid: %~sfilename%

For valid formats type CALL /? or FOR /?

如果 short1.bat 能够运行,我该如何将其转换为一个可以用 cmd.exe \c ... 来调用的单行命令?
还有一个问题(如何获取 DOS 路径而不是 Windows 路径),但那个问题专门询问当前目录的路径。

@dbenham:不行吗?啊好吧。值得一试。 - Chris Morgan
你为什么需要短名称呢?那是遗留功能,除非绝对必要,最好避免使用。 - Harry Johnston
@HarryJohnston:我想要启动的程序需要这些特殊路径名称,因为它会因文件夹名称中的空格而混淆。 - user1251007
将文件名(或完整路径)用引号括起来,可以解决大多数由名称中包含空格而引起的问题。短名称可能不是必需的。如果不支持长文件名,则必须使用非常旧的软件。 - dbenham
2
@dbenham - 长文件名必须用引号括起来,这可能会使传递到常见例程(如psexec)中变得棘手-请参阅http://stackoverflow.com/questions/24905546/psexec-exited-with-error-code-1-double-quotes - Allan Bowe
显示剩余3条评论
3个回答

50
cmd /c for %A in ("C:\Documents and Settings\User\NTUSER.DAT") do @echo %~sA

1
@user1251007 - 我相当确定你卡住了,除非你能让管理员在网络驱动器上启用短文件名。但是短名称很可能被禁用是有原因的。 - dbenham
如果您是管理员,可以在提升的命令提示符下运行以下命令来启用短文件名(不带引号):“fsutil.exe behavior set disable8dot3 0”。 - trlkly
尝试从批处理文件中运行,但不起作用!...我还尝试在末尾添加%(%%〜sA)...但仍然不起作用。但是,从cmd中可以工作。 - A Khudairy
3
@AKhudairy - 这个问题特别是关于使用 cmd /c 命令行的解决方案。在批处理文件中,您必须将所有百分号加倍 - 您所需要的只是 for %%A in ("某个路径\某个文件.ext") do echo %%~sA - dbenham
不确定为什么,但是这个答案(以及其他答案)在Win10上对于外部(NTFS)驱动器不起作用,只适用于操作系统驱动器。 - user2173353
显示剩余5条评论

6

将filename.txt替换为您要转换为8.3的文件名

dir /x filename.txt

接下来,您需要使用空格作为分隔符 (\s 在正则表达式中) 将结果拆分。然后,带有 ~ 的值就是您的短文件名。如果您的文件名本来就很短,那么您将找不到包含 ~ 的字符串。


一种相当低效的方法。我认为调用批处理脚本会更加高效。 - Chris Morgan

0

这里有一个示例,它会读取注册表中“appdata\local”文件夹的位置并将其转换为短路径:

cls
@echo off
cd /d "%~dp0"
chcp 65001 >nul

for /f "skip=1" %%a in ('"wmic useraccount where name='%USERNAME%' get sid"') do (
    for %%b in (%%a) do set current_SID=%%b
)
set current_username=%USERNAME%
set current_userprofile=%USERPROFILE%

set key_to_read=HKEY_USERS\%current_SID%\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
set value_to_read=Local AppData
rem If value_to_read contains ? space(s) set tokens to 2+?
for /f "usebackq eol= tokens=3,* delims= " %%a in (`reg query "%key_to_read%" /v "%value_to_read%" 2^>nul ^| find "%value_to_read%"`) do (
    set value_type=%%a
    set data_read=%%b
)
set data_read=%data_read:USERPROFILE=current_userprofile%
call set "data_read=%data_read%"
set current_local_appdata=%data_read%

set current_local_appdata_temp=%current_local_appdata%\Temp
echo %current_local_appdata_temp%

for %%a in ("%current_local_appdata_temp%") do set "current_local_appdata_temp_short=%%~sa"
echo %current_local_appdata_temp_short%

pause
exit

很遗憾,您的回答并没有回答问题。因此,它可能会在未来被删除。但是,它可能对其他人有用。我建议您提出一个新问题(即使您知道答案),然后直接回答该问题。 - user1251007

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接