DATA Step, Macro, Functions and more

Convert Long filename to Short (Dos) filename

Reply
Contributor
Posts: 61

Convert Long filename to Short (Dos) filename

Does anyone have a macro utility or procedure that can convert the longform windows file names to the short form dos version? For example, the path c:\program files becomes something like c:\progra~1. Also this takes place at the file name level as well where "one two three four.xlsx" ends up something like onetwo~1.xls.

Thanks.
PROC Star
Posts: 7,360

Re: Convert Long filename to Short (Dos) filename

I thought I had responded, but my post never showed up on the forum.

You can always use a pipe to send and retrieve the results of a dir/x command.

Art
-----------
> Does anyone have a macro utility or procedure that
> can convert the longform windows file names to the
> short form dos version? For example, the path
> c:\program files becomes something like c:\progra~1.
> Also this takes place at the file name level as well
> where "one two three four.xlsx" ends up something
> like onetwo~1.xls.
>
> Thanks.
Respected Advisor
Posts: 3,777

Re: Convert Long filename to Short (Dos) filename

Try this....

[pre]
%let Path = .\nPercenOfManyVars.sas;
%let Path = ..;
data ShortName(keep=Path Long: Short: Type);
attrib Path length=$256;
attrib Type length=$8;
attrib LongPathName length=$256;
attrib ShortPathName length=$256;
attrib LongFileName length=$256;
attrib ShortFileName length=$256;
length script filevar command $256;
Path = symget('Path');
script = catx('\',pathname('WORK'),'SHORTPATH.vbs');
filevar = script;

/* Write the script */
file dummy1 filevar=script;
put Path=$quote258.;
infile cards eof=eof;
do while(1);
input;
put _infile_;
end;
eof:
/* close the script file by opening another, not used */
filevar = catx('\',pathname('WORK'),'DUMMY.vbs');
file dummy1 filevar=filevar;

/* look at the script useful for debuging, errors referenced by (row,column) as (13, 7)*/
infile dummy2 filevar=script end=eof;
file log ls=256;
put 'NOTE: ' Script=;
put 'RULE: ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0';
do _n_ = 1 by 1 while(not eof);
input;
putlog 'NOTE-' _n_ z4. @11 _infile_;
end;

/* call the script */
command = catx(' ','cscript //nologo',quote(strip(script)));
infile dummy3 pipe filevar=command end=eof length=l lrecl=512;

put 'NOTE: Data lines returned from: ' command=;
put 'RULE: ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0';
do _n_ = 1 by 1 while(not eof);
input (_all_)(=);
putlog 'NOTE-' _n_ z4. @11 _infile_;
end;
_error_ = 0;
output;
stop;
cards4;
On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
WScript.Echo "Path=" & path
set f = fso.GetFile(Path)
if err.number <> 0 then
err.number = 0
set f = fso.Getfolder(Path)
if err.number <> 0 then
WSCript.Echo "LongPathName="
else
t = "Folder"
s = f.ShortPath
WScript.Echo "LongPathName=" & f
WScript.Echo "ShortPathName=" & s
Wscript.Echo "Type=" & t
end if
else
s = f.ShortPath
sn = f.ShortName
n = f.Name
t = "File"
WSCript.Echo "LongPathName=" &f
WSCript.Echo "ShortPathName=" &s
WSCript.Echo "LongFileName=" &n
WSCript.Echo "ShortFileName=" &sn
Wscript.Echo "Type=" & t

end if
;;;;
run;
proc print;
run;
proc transpose out=ShortNames;
var _all_;
run;
proc print;
run;
[/pre]
Regular Contributor
Posts: 241

Re: Convert Long filename to Short (Dos) filename

You can ask windows kernel via modulen. Packaging it neatly into a user-written function (or a macro) is left as an exercise for the interested reader(s). :-)

/* cd to work */
%let pwd = %sysfunc(pathname(work));
%put pwd=&pwd;
x cd &pwd;

/* create a test file with a long name */
%let long = long file name.txt;
options noxwait;
x "copy nul ""&long""";

/* create sascbtbl */
filename sascbtbl catalog "work.winapi.fm.source";
data _null_;
   file sascbtbl; input; put _infile_;
cards4;
routine GetShortPathNameA module=KERNEL32 minarg=3 maxarg=3 stackpop=called returns=long;
arg 1 input char format=$cstr256.; 
arg 2 output char format=$cstr256.; 
arg 3 input num format=pib4.;
;;;;
run;

/* call the win32 api func via modulen */
data _null_;
   length long short $256;
   long = "&long" || byte(0);
   short = byte(0);

   rc = modulen("*e", "GetShortPathNameA", long, short, 0);
   short = scan(short, 1, byte(0));
   if rc=0 then
      put "Uh-oh!";
   else
      put (long short) (= :quote.);
run;
filename sascbtbl clear;

/* on log
long="long file name.txt " short="LONGFI~1.TXT"
*/

Super User
Posts: 9,671

Re: Convert Long filename to Short (Dos) filename

Or If you like batch file.
Assuming all the files are in c:\temp directory.


[pre]
filename fname pipe 'dir c:\temp\*.* /b';
data _null_;
file 'c:\rename.bat';
infile fname length=len;
input name $varying100. len;
if (length(scan(name,1,'.')) gt 8) then do;
if findc(strip(name),' ') then do;
rename='rename '||strip(scan(name,1,' .'))||'*.'||strip(scan(name,-1,'.'))||
' '||strip(substr(compress(name),1,6))||'~1.'||strip(scan(name,-1,'.'));
put rename;
end;
else if findc(strip(name),'.') then do;
rename='rename '||strip(name)||' '||
strip(substr(compress(name),1,6))||'~1.'||strip(scan(name,-1,'.'));
put rename;
end;
else do;
rename='rename '||strip(name)||' '||strip(substr(compress(name),1,6))||'~1';
put rename;
end;
end;
run;
x "cd c:\temp\";
x "c:\rename.bat";
x "del c:\rename.bat";
run;
[/pre]

Ksharp
Ask a Question
Discussion stats
  • 4 replies
  • 1466 views
  • 0 likes
  • 5 in conversation