Linux环境下禁用XCMD时,如何递归获取SAS数据集创建日期?
纯SAS宏实现无XCMD环境下的目录递归扫描与日期获取
以下是完全基于SAS内部函数和语句实现的方案,无需依赖XCMD或系统命令,可在Linux环境下完成目录递归扫描、提取SAS数据集内部创建日期以及其他文件的修改日期:
步骤1:初始化结果数据集
先创建用于存储扫描结果的空数据集,定义字段类型与长度:
data file_info; length dir_path $256 file_name $128 file_type $16 create_date datetime. modify_date datetime.; stop; run;
步骤2:递归扫描宏定义
%macro scan_dir(root_dir); %local did i fname full_path fref fid rc libref create_date modify_date; /* 打开目标目录,失败则终止当前分支 */ %let did = %sysfunc(dopen(&root_dir)); %if &did. = 0 %then %do; %put ERROR: 无法访问目录: &root_dir.; %return; %end; /* 遍历目录下所有条目 */ %let i = 1; %let fname = %sysfunc(dread(&did., &i.)); %do %while(&fname. ne ); %let full_path = &root_dir./&fname.; /* 判断当前条目为目录还是文件 */ %if %sysfunc(doptname(&did., &i.)) = DIRECTORY %then %do; /* 跳过当前目录(.)和上级目录(..),递归扫描子目录 */ %if &fname. ne . and &fname. ne .. %then %do; %scan_dir(&full_path.); %end; %end; %else %do; /* 获取文件修改日期 */ %let fref = TMP_FILE_HANDLE; %let fid = %sysfunc(fopen(&fref., &full_path., S)); %if &fid. > 0 %then %do; %let modify_date = %sysfunc(attrn(&fid., MODATE)); %let rc = %sysfunc(fclose(&fid.)); %let create_date = .; /* 处理SAS数据集文件(.sas7bdat),提取内部创建日期 */ %if %sysfunc(scan(&fname., -1, .)) = sas7bdat %then %do; %let libref = TMP_LIB; /* 临时挂载目录为SAS库 */ %let rc = %sysfunc(libname(&libref., &root_dir.)); %if &rc. = 0 %then %do; /* 通过字典表读取数据集创建日期 */ proc sql noprint; select crdate into :create_date trimmed from dictionary.tables where libname = upcase("&libref.") and memname = upcase("%sysfunc(scan(&fname., 1, .))"); quit; /* 清理临时库 */ %let rc = %sysfunc(libname(&libref., clear)); /* 若字典表未找到,尝试直接读取文件头(兼容特殊情况) */ %if &create_date. = %then %do; %let fid = %sysfunc(fopen(&fref., &full_path., S, B)); %if &fid. > 0 %then %do; /* SAS7BDAT文件头16-23字节为创建时间(8字节整数格式) */ %let rc = %sysfunc(fseek(&fid., 16, 0)); %let raw_date = %sysfunc(fget(&fid., 8)); %let create_date = %sysfunc(inputn(&raw_date., IB8.)); %let rc = %sysfunc(fclose(&fid.)); %end; %end; %end; %else %do; %put WARNING: 无法挂载目录&root_dir.,无法获取&fname.的创建日期; %end; %end; /* 将结果写入数据集 */ proc sql noprint; insert into file_info values ("&root_dir." "&fname." "%sysfunc(scan(&fname., -1, .))" &create_date. &modify_date.); quit; %end; %else %do; %put WARNING: 无法打开文件: &full_path.; %end; %end; %let i = %eval(&i. + 1); %let fname = %sysfunc(dread(&did., &i.)); %end; /* 关闭目录句柄 */ %let rc = %sysfunc(dclose(&did.)); %mend scan_dir;
步骤3:调用宏并查看结果
/* 指定要扫描的根目录 */ %scan_dir(/your/target/directory/path); /* 格式化输出结果 */ proc print data=file_info noobs; var dir_path file_name file_type create_date modify_date; format create_date modify_date datetime20.; title '文件扫描结果'; run;
关键说明
- 递归扫描逻辑:通过
dopen/dread/dclose函数遍历目录,遇到子目录时递归调用自身实现深度遍历 - SAS数据集创建日期:优先通过临时挂载目录为SAS库,读取
dictionary.tables中的crdate字段;若失败则直接读取SAS7BDAT文件头的指定偏移量(兼容多数SAS版本) - 普通文件修改日期:通过
fopen打开文件后,用attrn函数提取MODATE属性 - 权限要求:确保SAS进程对目标目录及所有子目录、文件有读取权限
内容的提问来源于stack exchange,提问作者Aamir Warsi
相关产品推荐
相关产品推荐

