From ddd831fe7a9caf93be45a630644af9db17df251b Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Mon, 29 Nov 2021 11:35:03 +0000 Subject: [PATCH 1/2] feat: new copyfolder macro and associated test. Closes #92 --- base/mp_copyfolder.sas | 78 ++++++++++++++++++++++ base/mp_dirlist.sas | 1 + tests/crossplatform/mp_copyfolder.test.sas | 52 +++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 base/mp_copyfolder.sas create mode 100644 tests/crossplatform/mp_copyfolder.test.sas diff --git a/base/mp_copyfolder.sas b/base/mp_copyfolder.sas new file mode 100644 index 0000000..dfbed16 --- /dev/null +++ b/base/mp_copyfolder.sas @@ -0,0 +1,78 @@ +/** + @file + @brief A macro to recursively copy a directory + @details Performs a recursive directory listing then works from top to bottom + copying files and creating subdirectories. + + Usage: + + %let rootdir=%sysfunc(pathname(work))/demo; + %let copydir=%sysfunc(pathname(work))/demo_copy; + %mf_mkdir(&rootdir) + %mf_mkdir(&rootdir/subdir) + %mf_mkdir(&rootdir/subdir/subsubdir) + data "&rootdir/subdir/example.sas7bdat"; + run; + + %mp_copyfolder(&rootdir,©dir) + + @param source Unquoted path to the folder to copy from. + @param target Unquoted path to the folder to copy to. + +

SAS Macros

+ @li mf_getuniquename.sas + @li mf_isdir.sas + @li mf_mkdir.sas + @li mp_abort.sas + @li mp_dirlist.sas + +

Related Macros

+ @li mp_copyfolder.test.sas + +**/ + +%macro mp_copyfolder(source,target); + + %mp_abort(iftrue=(%mf_isdir(&source)=0) + ,mac=&sysmacroname + ,msg=%str(Source dir does not exist (&source)) + ) + + %mf_mkdir(&target) + + %mp_abort(iftrue=(%mf_isdir(&target)=0) + ,mac=&sysmacroname + ,msg=%str(Target dir could not be created (&target)) + ) + + /* prep temp table */ + %local tempds; + %let tempds=%mf_getuniquename(); + + /* recursive directory listing */ + %mp_dirlist(path=&source,outds=work.&tempds, maxdepth=MAX) + + /* create folders and copy content */ + data _null_; + set work.&tempds; + filepath2="&target/"!!substr(filepath,%length(&source)+2); + if file_or_folder='folder' then call execute('%mf_mkdir('!!filepath2!!')'); + else do; + length fref1 fref2 $8; + rc1=filename(fref1,filepath,'disk','recfm=n'); + rc2=filename(fref2,filepath2,'disk','recfm=n'); + if fcopy(fref1,fref2) ne 0 then do; + sysmsg=sysmsg(); + putlog "%str(ERR)OR: Unable to copy " filepath " to " filepath2; + putlog sysmg=; + end; + end; + rc=filename(fref1); + rc=filename(fref2); + run; + + /* tidy up */ + proc sql; + drop table work.&tempds; + +%mend mp_copyfolder; \ No newline at end of file diff --git a/base/mp_dirlist.sas b/base/mp_dirlist.sas index 504ec36..371ddbf 100644 --- a/base/mp_dirlist.sas +++ b/base/mp_dirlist.sas @@ -202,6 +202,7 @@ run; data _null_; set &out_ds; where file_or_folder='folder'; + length code $10000; code=cats('%nrstr(%mp_dirlist(path=',filepath,",outds=&outds" ,",getattrs=&getattrs,level=%eval(&level+1),maxdepth=&maxdepth))"); put code=; diff --git a/tests/crossplatform/mp_copyfolder.test.sas b/tests/crossplatform/mp_copyfolder.test.sas new file mode 100644 index 0000000..4594b6f --- /dev/null +++ b/tests/crossplatform/mp_copyfolder.test.sas @@ -0,0 +1,52 @@ +/** + @file + @brief Testing mp_copyfolder.sas macro + +

SAS Macros

+ @li mp_copyfolder.sas + @li mf_mkdir.sas + @li mf_nobs.sas + @li mp_assert.sas + @li mp_dirlist.sas + +**/ + +/** + * make a directory structure + */ + +%let root=%sysfunc(pathname(work))/top; +%mf_mkdir(&root) +%mf_mkdir(&root/a) +%mf_mkdir(&root/b) +%mf_mkdir(&root/a/d) +%mf_mkdir(&root/a/e) +%mf_mkdir(&root/a/e/f) +data "&root/a/e/f/ds1.sas7bdat";x=1; +data "&root/a/e/ds2.sas7bdat";x=1; +data "&root/a/ds3.sas7bdat";x=1; +run; + +%mp_dirlist(path=&root, outds=myTable, maxdepth=MAX) + +%mp_assert( + iftrue=(%mf_nobs(work.mytable)=8), + desc=Temp data successfully created, + outds=work.test_results +) + +/** + * copy it + */ +%let newfolder=%sysfunc(pathname(work))/new; +%mp_copyfolder(&root,&newfolder) + +%mp_dirlist(path=&newfolder, outds=work.myTable2, maxdepth=MAX) + +%mp_assert( + iftrue=(%mf_nobs(work.mytable2)=8), + desc=Folder successfully copied, + outds=work.test_results +) + + From 02de4e42bfad4a1de2acd2113bdaa9bf7ac8f245 Mon Sep 17 00:00:00 2001 From: Allan Bowe Date: Mon, 29 Nov 2021 11:35:37 +0000 Subject: [PATCH 2/2] chore: generating all.sas and fixing indentation --- all.sas | 78 ++++++++++++++++++++++ tests/crossplatform/mp_copyfolder.test.sas | 4 +- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/all.sas b/all.sas index 1e8ec11..5361f00 100644 --- a/all.sas +++ b/all.sas @@ -2723,6 +2723,83 @@ run; run; %mend mp_cleancsv; /** @endcond *//** + @file + @brief A macro to recursively copy a directory + @details Performs a recursive directory listing then works from top to bottom + copying files and creating subdirectories. + + Usage: + + %let rootdir=%sysfunc(pathname(work))/demo; + %let copydir=%sysfunc(pathname(work))/demo_copy; + %mf_mkdir(&rootdir) + %mf_mkdir(&rootdir/subdir) + %mf_mkdir(&rootdir/subdir/subsubdir) + data "&rootdir/subdir/example.sas7bdat"; + run; + + %mp_copyfolder(&rootdir,©dir) + + @param source Unquoted path to the folder to copy from. + @param target Unquoted path to the folder to copy to. + +

SAS Macros

+ @li mf_getuniquename.sas + @li mf_isdir.sas + @li mf_mkdir.sas + @li mp_abort.sas + @li mp_dirlist.sas + +

Related Macros

+ @li mp_copyfolder.test.sas + +**/ + +%macro mp_copyfolder(source,target); + + %mp_abort(iftrue=(%mf_isdir(&source)=0) + ,mac=&sysmacroname + ,msg=%str(Source dir does not exist (&source)) + ) + + %mf_mkdir(&target) + + %mp_abort(iftrue=(%mf_isdir(&target)=0) + ,mac=&sysmacroname + ,msg=%str(Target dir could not be created (&target)) + ) + + /* prep temp table */ + %local tempds; + %let tempds=%mf_getuniquename(); + + /* recursive directory listing */ + %mp_dirlist(path=&source,outds=work.&tempds, maxdepth=MAX) + + /* create folders and copy content */ + data _null_; + set work.&tempds; + filepath2="&target/"!!substr(filepath,%length(&source)+2); + if file_or_folder='folder' then call execute('%mf_mkdir('!!filepath2!!')'); + else do; + length fref1 fref2 $8; + rc1=filename(fref1,filepath,'disk','recfm=n'); + rc2=filename(fref2,filepath2,'disk','recfm=n'); + if fcopy(fref1,fref2) ne 0 then do; + sysmsg=sysmsg(); + putlog "%str(ERR)OR: Unable to copy " filepath " to " filepath2; + putlog sysmg=; + end; + end; + rc=filename(fref1); + rc=filename(fref2); + run; + + /* tidy up */ + proc sql; + drop table work.&tempds; + +%mend mp_copyfolder;/** @file mp_createconstraints.sas @brief Creates constraints @details Takes the output from mp_getconstraints.sas as input @@ -3337,6 +3414,7 @@ run; data _null_; set &out_ds; where file_or_folder='folder'; + length code $10000; code=cats('%nrstr(%mp_dirlist(path=',filepath,",outds=&outds" ,",getattrs=&getattrs,level=%eval(&level+1),maxdepth=&maxdepth))"); put code=; diff --git a/tests/crossplatform/mp_copyfolder.test.sas b/tests/crossplatform/mp_copyfolder.test.sas index 4594b6f..2e91652 100644 --- a/tests/crossplatform/mp_copyfolder.test.sas +++ b/tests/crossplatform/mp_copyfolder.test.sas @@ -36,8 +36,8 @@ run; ) /** - * copy it - */ + * copy it + */ %let newfolder=%sysfunc(pathname(work))/new; %mp_copyfolder(&root,&newfolder)