36

I am trying to convert a long filename to a short filename (8.3) on Windows.

A batch-file with a command line argument works as intended:

short.bat:

@echo OFF
echo %~s1

calling short.bat C:\Documents and Settings\User\NTUSER.DAT returns C:\DOCUM~1\USER\NTUSER.DAT

However, I don't like having an extra .bat-file for this. I would rather call cmd.exe with the whole command from a ruby script. How can I do this?

As an intermediate step I tried to hardcode the path in the batch-file, but that does not work:

short1.bat:

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

echo %filename% works, but echo %~sfilename% gives the following error:

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

For valid formats type CALL /? or FOR /?

If short1.bat works, how can I convert this into a one-liner that can be called with cmd.exe \c ...?

There is another question (how to get DOS path instead of Windows path), however that one is specifically asking for the path of the current directory.

Community
  • 1
  • 1
user1251007
  • 15,891
  • 14
  • 50
  • 76
  • I don't have Windows immediately handy, but try `%filename:~s%` (similar style to the substring notation, `%filename:~0,1%`). If that works, I'll make an answer of it. – Chris Morgan Apr 19 '12 at 11:58
  • @ChrisMorgan - definitely not. Won't work. – dbenham Apr 19 '12 at 12:03
  • @dbenham: no? ah well. It was worth a try. – Chris Morgan Apr 19 '12 at 12:04
  • Why do you need the short name anyway? That's legacy functionality, best avoided unless absolutely necessary. – Harry Johnston Apr 20 '12 at 04:51
  • @HarryJohnston: a program that I wan't to start needs this special path names as it gets confused by the spaces in folder names. – user1251007 Apr 20 '12 at 10:53
  • Your best bet may be to copy the target file to the local file system. – Harry Johnston Apr 21 '12 at 03:35
  • Enclosing file names (or full paths) within quotes solves most problems that arise from spaces within names. Short names may not be necessary. If would have to be very old software to not support long file names. – dbenham Apr 16 '14 at 11:21
  • 2
    @dbenham - long file names have to be in quotes, which can be tricky to pass into common routines such as psexec - see http://stackoverflow.com/questions/24905546/psexec-exited-with-error-code-1-double-quotes – Allan Bowe Jul 23 '14 at 10:19

3 Answers3

50
cmd /c for %A in ("C:\Documents and Settings\User\NTUSER.DAT") do @echo %~sA
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • This works fine on my local drive, but not on a mapped network-drive. Any ideas? – user1251007 Apr 19 '12 at 13:15
  • @user1251007 - What version of Windows are you using? There is a known XP bug dealing with 8.3 names and the ~s modifier: http://stackoverflow.com/questions/8354305/batch-parameter-s1-gives-incorrect-8-3-short-name – dbenham Apr 19 '12 at 13:46
  • @user1251007 - Also, generation of 8.3 file names can be disabled for a given drive by the administrator. Can you verify that DIR /X gives short file names on your network drive? – dbenham Apr 19 '12 at 13:50
  • I am using Windows XP, but the bug has nothing to do with it. It simply does not change the whole path at all. It seems to be, that this feature is disabled, as DIR \X does not give short file names. Is there any way around this? – user1251007 Apr 19 '12 at 14:18
  • 1
    @user1251007 - I am fairly certain you are stuck, unless you can get your administrator to enable short file names on your network drives. But short names are probably disabled for a reason. – dbenham Apr 19 '12 at 14:28
  • @dbenham: +1, short names are a monstrosity. They can cause all sorts of problems, especially in a server context. – Harry Johnston Apr 20 '12 at 04:50
  • If you are the administrator, you can enable short filenames by runing the following command at an elevated command prompt (without the quotes): "fsutil.exe behavior set disable8dot3 0" – trlkly Apr 16 '14 at 07:24
  • Tried this from a batch file and it doesnt work! ... i tried also adding % at the end (%%~sA) ... but still doesn't work. However it works from cmd – A Khudairy Apr 05 '16 at 08:20
  • 3
    @AKhudairy - This question was specifically about a solution for the command line using `cmd /c`. Within a batch file you must double all percents - All you need is `for %%A in ("some path here\some file.ext") do echo %%~sA` – dbenham Apr 05 '16 at 11:16
  • Not sure why, but this (as well as other answers here...) does not work for external (NTFS) drives on Win10, but only for the OS drive. – user2173353 Apr 30 '22 at 11:08
6

Replace the filename.txt to the filename you want to convert to 8.3

dir /x filename.txt

You will then have to split the result with whitespace as your delimiter (\s in regex). Then the value with the ~ is your short filename. If your filename is short to begin with, then you won't find a string containing a ~.

Robert Louis Murphy
  • 1,558
  • 1
  • 16
  • 29
0

Here is an example that read in the registry the location of your "appdata\local" folder and convert it to short path:

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
Celes
  • 27
  • 1
  • 5
  • Unfortunately your answer does not answer the question. Thus it might be deleted in the future. However, it might be useful for others. I would suggest that you ask a new question (even if you know the answer), and directly answer that question yourself. – user1251007 Apr 11 '20 at 12:20