BookmarkSubscribeRSS Feed
wcpatton
Calcite | Level 5
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.
4 REPLIES 4
art297
Opal | Level 21
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.
data_null__
Jade | Level 19
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]
chang_y_chung_hotmail_com
Obsidian | Level 7

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"
*/

Ksharp
Super User
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 😎 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

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 4080 views
  • 1 like
  • 5 in conversation