Преобразовать длинное имя файла в короткое имя файла (8.3) с помощью cmd.exe

Я пытаюсь преобразовать длинное имя файла в короткое имя файла (8.3) в Windows.

Пакетный файл с аргументом командной строки работает как задумано:

short.bat:

@echo OFF
echo %~s1

призвание short.bat C:\Documents and Settings\User\NTUSER.DAT возвращается C:\DOCUM~1\USER\NTUSER.DAT

Однако мне не нравится иметь дополнительный.bat-файл для этого. Я бы предпочел позвонить cmd.exe со всей командой из сценария ruby. Как я могу это сделать?

В качестве промежуточного шага я попытался жестко закодировать путь в пакетном файле, но это не работает:

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), однако этот вопрос специально задает путь к текущему каталогу.

2 ответа

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

Замените filename.txt на имя файла, который вы хотите конвертировать в 8.3

dir /x filename.txt

Затем вам нужно разделить результат с пробелами в качестве разделителя (\s в регулярном выражении). Тогда значение с ~ это ваше короткое имя файла. Если ваше имя файла короткое для начала, то вы не найдете строку, содержащую ~.

Вот пример, который считывает в реестре местоположение вашей папки "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
Другие вопросы по тегам