Repository to share SAS Studio Custom Steps. A custom step enables you to create a user interface for SAS Studio users at your site to complete a specific task.
Apache License 2.0
49
stars
64
forks
source link
[BUG] Create Listing of Directory - CLOD : Directories do not reflect in output even after option is selected. #163
Describe the bug
Hi @stephanweigandt , I provide some screenshots with the parameters I changed. I explicitly selected Yes to "Include Directories in Output" and chose to list contents only at root level (traverse = No).
I noticed a debug mode and ran it with 1. Log is shown below. I see only the files printed, not the directories.
Note
My ideal output is to list only folders within a directory. But there's no option to say list only folders (directories) in output. This might be a feature request in addition to resolving this issue :).
To Reproduce
Steps to reproduce the behavior:
Plain vanilla run of custom step in a flow, with only change made to "Traverse subdirectories - No" and Include directories - Yes.
Expected behavior
I expected to see all files and directories as part of output. Repeating note above.
Screenshots
Added shots of parameter choices and output.
193 /*===========================================================================*
194 * Node name: PY_SAS_Create Listing Of Directory CLOD
195 * Node ID: id-1724871581560-7807
196 *
197 * Output Tables:
198 * WORK.FILENAMES_NEW
199 *
200 * Step name: PY_SAS_Create Listing Of Directory CLOD
201 * Step path: /dataFlows/steps/fb7b7264-bd26-4959-81d7-077122da2546
202 * Step description:
203 *----------------------------------------------------------------------------*/
204
205 /* region: Generated step setup */
206 %_flw_action_start(id-1724871581560-7807);
_FLW_ACTION_START_|2024-08-28T15:05:58+00:00|id-1724871581560-7807
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
207 /* endregion */
208
209 /* region: Generated macro initialization */
210
211 /* Define utility macros - BEGIN */
212
213 /* Macro to get a list of column names */
214 %macro _flw_get_column_list(_flw_prefix = %nrstr(), _delim=%str( ));
215 %do _flw_index=1 %to %unquote(&&&_flw_prefix._count);%unquote(&&&_flw_prefix._&_flw_index._name)%if
215 ! &_flw_index.<%unquote(&&&_flw_prefix._count)%then&_delim.; %end;
216 %mend;
217
218 /* Macro to delete macro variables with names passed in */
219 %macro _flw_del_macro_vars(_flw_macro_vars_to_delete,_flw_no_warn=Y);
220 %if "&_flw_no_warn"="Y" %then %symdel &_flw_macro_vars_to_delete/NOWARN;
221 %else %symdel &_flw_macro_vars_to_delete;
222 %mend;
223
224 /* Macro to delete a list of macros with names passed in */
225 %macro _flw_del_macros(_flw_macro_names,_flw_no_warn=Y);
226 %let num=1;
227 %let _flw_local_macros_to_delete=%scan(&_flw_macro_names,&num);
228 %do %while (&_flw_local_macros_to_delete ne );
229 %if "&_flw_no_warn"="Y" %then %sysmacdelete &_flw_local_macros_to_delete/NOWARN;
230 %else %sysmacdelete &_flw_local_macros_to_delete;
231 %let num=%eval(&num+1);
232 %let _flw_local_macros_to_delete=%scan(&_flw_macro_names,&num);
233 %end;
234 %mend;
235
236 /* Define utility macros - END */
237
238 /* Macro variables derived from user input to this step - BEGIN */
239
240 /* Macro variable(s) for UI control with ID of Extension_ui */
241 %let Extension_ui=%nrquote(*);
242
243 /* Macro variable(s) for UI control with ID of cas_promote_ui */
244 %let cas_promote_ui=0;
245
246 /* Macro variable(s) for UI control with ID of cas_save_on_disk_ui */
247 %let cas_save_on_disk_ui=0;
248
249 /* Macro variable(s) for UI control with ID of clod_traverse_directories_ui */
250 %let clod_traverse_directories_ui=0;
251
252 /* Macro variable(s) for UI control with ID of debug_mode_ui */
253 %let debug_mode_ui=1;
254
255 /* Macro variable(s) for UI control with ID of include_directories_ui */
256 %let include_directories_ui=1;
257
258 /* Macro variable(s) for UI control with ID of log_file_path_ui */
259 %let log_file_path_ui=;
260
261 /* Macro variable(s) for UI control with ID of options_seq_ui */
262 %let options_seq_ui=;
263
264 /* Macro variable(s) for UI control with ID of outputtable_ui */
265 %let outputtable_ui=WORK.FILENAMES_NEW;
266 %let outputtable_ui_engine=V9;
267 %let outputtable_ui_label=;
268 %let outputtable_ui_lib=WORK;
269 %let outputtable_ui_name=FILENAMES_NEW;
270 %let outputtable_ui_name_base=FILENAMES_NEW;
271 %let outputtable_ui_tblType=table;
272 %let outputtable_ui_type=dataTable;
273
274 /* Macro variable(s) for UI control with ID of root_directory_ui */
275 %let root_directory_ui=%nrquote(sasserver:/mnt/viya-share/data/sas-studio-custom-steps);
276
277 /* Macro variable(s) for UI control with ID of write_log_into_file_ui */
278 %let write_log_into_file_ui=0;
279
280 /* Macro variables derived from user input to this step - END */
281
282 /* endregion */
283 /* SAS code provided in template section of Custom Step - BEGIN */
284 /******************************************************************************
285 %adjust_option_setings_controlled
286 ________
287 Helps to maintain option changes in a program flow.
288 ______________________________________________________________________________
289
290 USAGE: %adjust_option_setings_controlled(aosc_option_seq = ,
291 aosc_temp_option_storage_ds = ,
292 aosc_running_mode = ,
293 aosc_validvarname_setting =
294 )
295 ______________________________________________________________________________
296
297 DESCRIPTION:
298
299 When option changes occur (only single word options allowed), then this macro
300 helps to maintain the original option setting, so at the end, the system can
301 revert back to the original settings.
302 ______________________________________________________________________________
303
304 INPUT PARAMETERS AND KEYWORDS:
305
306 aosc_option_seq This can be a blank separated list of single word
307 SAS options (e.g. like: source, notes, etc...).
308 If empty nothing happens in CHANGE mode.
309 aosc_temp_option_storage_ds provide the full dataset name (e.g. work._aosc_setting_storage)
310 where the original option values (of the ones that are
311 provided in AOSC_OPTION_SEQ) are stored.
312 aosc_running_mode 2 modes available:
313 CHANGE: takes settings from AOSC_OPTION_SEQ and applies
314 those
315 RESET: if AOSC_TEMP_OPTION_STORAGE_DS exists, this mode
316 will set options back according to content of
317 this dataset.
318 aosc_validvarname_setting if not blank, validvarname will be set to the value
319 as provided with this parameter
320 _________________________________________________________________________
321
322 CALLS: none.
323 ______________________________________________________________________________
324
325 NOTES: (Initials, date, summary)
326
327 Stephan Weigandt 20220922 First officially Released Version
328 ______________________________________________________________________________
329
330 *******************************************************************************/
331
332 %macro adjust_option_setings_controlled(
333 aosc_option_seq = ,
334 aosc_temp_option_storage_ds = work._aosc_temp_option_storage_ds,
335 aosc_running_mode = ,
336 aosc_validvarname_setting =
337 );
338
339
340 %if %upcase("&aosc_running_mode") = "CHANGE" %then
341 %do;
342 data &aosc_temp_option_storage_ds;
343 length
344 new_setting $24.
345 original_setting $24.
346 new_single_setting_seq $256.
347 ;
348 new_setting = "";
349 original_setting = "";
350 new_single_setting_seq = "";
351 numberofsettings = 0;
352 additional_option_setting = 0;
353 if 0;
354 run;
355
356 %if "&aosc_option_seq" ne "" or
357 "&aosc_validvarname_setting" ne "" %then
358 %do;
359 data &aosc_temp_option_storage_ds;
360 length
361 new_setting $24.
362 original_setting $24.
363 new_single_setting_seq $256.
364 ;
365 new_single_setting_seq = strip("&aosc_option_seq");
366 %if "&aosc_validvarname_setting" ne "" %then
367 %do;
368 original_setting = getoption("validvarname");
369 additional_option_setting = 1;
370 new_setting = "&aosc_validvarname_setting";
371 output;
372 call execute("option validvarname = "||new_Setting||";");
373 %end;
374 %if "&aosc_option_seq" ne "" %then
375 %do;
376 numberofsettings = count(new_single_setting_seq, " ") + 1;
377 additional_option_setting = 0;
378 do i = 1 to numberofsettings;
379 new_setting = "";
380 new_setting = scan(new_single_setting_seq, i, " ");
381 if not missing(new_setting) then
382 do;
383 original_setting = getoption(new_setting);
384 output;
385 call execute("option "||new_Setting||";");
386 end;
387 end;
388 %end;
389 run;
390 %end;
391 %end;
392
393 %if %upcase("&aosc_running_mode") = "RESET" %then
394 %do;
395 %if %sysfunc(exist(&aosc_temp_option_storage_ds)) %then
396 %do;
397 data _null_;
398 set &aosc_temp_option_storage_ds;
399 if additional_option_setting = 1 then
400 do;
401 call execute("option validvarname = "||original_setting||";");
402 end; else
403 do;
404 call execute("option "||original_setting||";");
405 end;
406 run;
407 %end;
408 %end;
409 %mend adjust_option_setings_controlled;
410
411 /** FOR TESTING ***
412 option nomprint nosource notes ;
413 %let option_seq = mprint notes source;
414 %let running_mode = CHANGE;
415 %let validvarname_setting = any;
416
417 %put PRECHANGE;
418 %put VALIDVARNAME: %sysfunc(getoption(validvarname));
419 %put SOURCE: %sysfunc(getoption(source));
420 %put NOTES: %sysfunc(getoption(notes));
421 %put MPRINT: %sysfunc(getoption(mprint));
422
423 %adjust_option_setings_controlled(
424 aosc_option_seq = &option_seq,
425 aosc_running_mode = &running_mode,
426 aosc_validvarname_setting = &validvarname_setting
427 );
428
429 %put POSTCHANGE;
430 %put VALIDVARNAME: %sysfunc(getoption(validvarname));
431 %put SOURCE: %sysfunc(getoption(source));
432 %put NOTES: %sysfunc(getoption(notes));
433 %put MPRINT: %sysfunc(getoption(mprint));
434
435
436 %let running_mode = RESET;
437
438 %adjust_option_setings_controlled(
439 aosc_running_mode = &running_mode
440 );
441
442 %put POSTRESET;
443 %put VALIDVARNAME: %sysfunc(getoption(validvarname));
444 %put SOURCE: %sysfunc(getoption(source));
445 %put NOTES: %sysfunc(getoption(notes));
446 %put MPRINT: %sysfunc(getoption(mprint));
447
448
449
450 *********************/
451
452 /**
453 store current SAS options settings, so they can be reset
454 at the end of processing
455 **/
456
457
458 %adjust_option_setings_controlled(
459 aosc_option_seq = &options_seq_ui,
460 aosc_running_mode = CHANGE,
461 aosc_validvarname_setting = any
462 );
NOTE: The data set WORK._AOSC_TEMP_OPTION_STORAGE_DS has 0 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: The data set WORK._AOSC_TEMP_OPTION_STORAGE_DS has 1 observations and 4 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: CALL EXECUTE generated line.
1 + option validvarname = any ;
463
464 %let clod_delimiter = ;
465 %macro set_os_dependent_values(
466 sodv_delimiter = clod_delimiter
467 );
468 %if %upcase(&SYSSCP) = WIN %then
469 %do;
470 %let &sodv_delimiter = \;
471 %end; %else
472 %do;
473 %let &sodv_delimiter = /;
474 %end;
475 %mend set_os_dependent_values;
476 %set_os_dependent_values(
477 sodv_delimiter = clod_delimiter
478 );
479
480 /******************************************************************************
481
482 %list_all_files
483 ________
484
485
486 creates a list of files, based on the provided extensions, that are available
487 within a root directory. It automatically also checks all subdirectories.
488
489 ______________________________________________________________________________
490
491
492 USAGE: see testing section on the bottom of this code
493
494 ______________________________________________________________________________
495
496 DESCRIPTION:
497
498 This macro creates a SAS dataset that lists all files that can be found within a
499 root directory and all subdirectories under the provided root directory.
500 This can be applied to all available files (by choosing "*" as extension),
501 or for specific extensions.
502 ______________________________________________________________________________
503
504
505 INPUT PARAMETERS AND KEYWORDS:
506
507 laf_root_dir provide the top level directory from
508 where to search for files.
509 laf_extenstion_to_check can be the wildcard "*" or
510 any extension, e.g. "CSV", "XLM" etc
511 (provide without quotes)
512 laf_output_ds_file_overview provide SAS datasets providing
513 LIBNAME and SAS Dataset name
514 ______________________________________________________________________________
515
516 NOTES: (Initials, date, summary)
517
518 Stephan Weigandt 20200406 First officially Released Version
519 Stephan Weigandt 20220610 expanded functionality to also cover
520 SAS Content objects
521 ______________________________________________________________________________
522
523 *******************************************************************************/
524
525 %macro list_all_files(
526 laf_root_dir,
527 laf_extenstion_to_check,
528 laf_output_ds_file_overview,
529 laf_debug_mode = 0,
530 laf_directory_separator = /,
531 laf_traverse_directories = 1,
532 laf_is_sas_content_directory = 0,
533 laf_iteration_number = 0_0,
534 laf_include_directories = 0
535 );
536 %local
537 filrf
538 rc
539 did
540 memcnt
541 name
542 lal_append_flag
543 lal_length
544 tot_obs
545 table_append_seq
546 laf_full_file_name
547 i
548 laf_debug_text_
549 ;
550
551 %let laf_debug_text_skipping = INFORMATION: Skipping due to extension:;
552 %let laf_debug_text_scanning = INFORMATION: Scanning next directory:;
553 %let lal_length = %length(&laf_root_dir);
554 %if "%substr(%trim(%left(&laf_root_dir)), &lal_length, 1)" ne
555 "%trim(%left(&laf_directory_separator))" %then
556 %do;
557 %let laf_root_dir = %trim(%left(&laf_root_dir))&laf_directory_separator;
558 %end;
559 %if &laf_iteration_number = 0_0 %then
560 %do;
561 proc datasets lib= work;
562 delete _LAF_spcl_list_files_:;
563 quit;
564 %end;
565 %let laf_do_processing = 1;
566 %if &laf_is_sas_content_directory = 0 %then
567 %do;
568 filename f&laf_iteration_number "&laf_root_dir";
569 %end; %else
570 %do;
571 %let laf_rc = 1;
572 data _null_;
573 length fref $ 8 folderPath $ 1024;
574 folderPath = "&laf_root_dir";
575 fref="__isdir";
576 rcf = filename(fref, ,
577 "filesrvc",
578 cats('folderpath=',quote(strip(folderPath)))
579 );
580 put rcf;
581 call symput ("laf_rc", strip(rcf));
582 run;
583
584 %if &laf_rc = 0 %then
585 %do;
586 filename f&laf_iteration_number filesrvc folderpath="&laf_root_dir";
587 %end; %else
588 %do;
589 %let laf_do_processing = 0;
590 %end;
591 %end;
592 %let laf_next_iteration = %eval(%scan(&laf_iteration_number, 1, '_') + 1);
593 %let lal_append_flag = 0;
594 %if %sysfunc(exist(work._LAF_spcl_list_files_&laf_iteration_number)) %then
595 %do;
596 data work._LAF_spcl_list_files_&laf_iteration_number._inter;
597 set work._LAF_spcl_list_files_&laf_iteration_number
598 %if %sysfunc(exist(
599 work._LAF_spcl_list_files_&laf_iteration_number._inter
600 )) %then
601 %do;
602 work._LAF_spcl_list_files_&laf_iteration_number._inter
603 %end;
604 ;
605 run;
606 %let lal_append_flag = 1;
607 %end;
608 data work._LAF_spcl_list_files_&laf_iteration_number ;
609 keep
610 directory_path
611 full_file_name
612 file_name
613 is_in_SAS_Content_flag
614 %if &laf_include_directories = 1 %then
615 %do;
616 object_type
617 %end;
618 ;
619 length
620 directory_path $768
621 file_name $256
622 full_file_name $1024
623 %if &laf_include_directories = 1 %then
624 %do;
625 object_type $12
626 %end;
627 ;
628 is_in_SAS_Content_flag = &laf_is_sas_content_directory;
629 directory_path = symget("laf_root_dir");
630 %if &laf_do_processing = 1 %then
631 %do;
632 did = dopen("f&laf_iteration_number");
633 mcount = dnum(did);
634 /**
635 check if directory exists or the correct area is chosen.
636 if not set to 0 to prevent error message
637 **/
638 if missing(mcount) then
639 mcount = 0;
640 do i=1 to mcount;
641 file_name = dread(did, i);
642 fid = mopen(did, file_name);
643 fileext = find(file_name,'.');
644 extension = scan(file_name, -1, '.');
645 /* fid=0 means directory in most cases */
646 full_file_name = STRIP(directory_path)||STRIP(file_name);
647 if fid > 0 or fileext then
648 do;
649 if "&laf_extenstion_to_check" = "*" or
650 upcase(extension) = %upcase("&laf_extenstion_to_check") then
651 do;
652 %if &laf_debug_mode %then
653 %do;
654 put "INFORMATION: Found following file:" full_file_name;
655 %end;
656 %if &laf_include_directories = 1 %then
657 %do;
658 object_type = "file";
659 %end;
660 output;
661 end;
662 %if &laf_debug_mode %then
663 %do;
664 else
665 do;
666 put "&laf_debug_text_skipping" full_file_name;
667 end;
668 %end;
669 end;
670 %if &laf_traverse_directories = 1 %then
671 %do;
672 else
673 do;
674 %if &laf_debug_mode %then
675 %do;
676 put "&laf_debug_text_scanning" full_file_name;
677 %end;
678 %if &laf_include_directories = 1 %then
679 %do;
680 object_type = "folder";
681 output;
682 %end;
683 arg1 = cats('%nrstr(%list_all_files(',
684 full_file_name,
685 ", &laf_extenstion_to_check,"
686 );
687 arg2 = cats("&laf_output_ds_file_overview,
688 laf_debug_mode = &laf_debug_mode,"
689 );
690 arg3 = cats("laf_directory_separator =
691 &laf_directory_separator,
692 laf_traverse_directories =
693 &laf_traverse_directories,"
694 );
695 arg3b = cats("laf_include_directories =
696 &laf_include_directories, "
697 );
698 arg4 = cats("laf_is_sas_content_directory =
699 &laf_is_sas_content_directory,
700 laf_iteration_number =
701 &laf_next_iteration._",i,"))"
702 );
703 call execute(strip(arg1)||
704 strip(arg2)||
705 strip(arg3)||
706 strip(arg3b)||
707 strip(arg4)
708 );
709 end;
710 %end;
711 end;
712 rc = dclose(did);
713 %end;
714 %else
715 %do;
716 full_file_name = STRIP(substr(directory_path,
717 1,
718 length(directory_path)-1)
719 );
720 %if &laf_include_directories = 1 %then
721 %do;
722 object_type = "file";
723 %end;
724
725 output;
726 %end;
727 run;
728
729
730 %let tot_obs = 0;
731 proc sql noprint;
732 select nobs into :tot_obs
733 from dictionary.tables
734 where upcase(libname)='WORK' and
735 upcase(memname)="_LAF_SPCL_LIST_FILES_&laf_iteration_number";
736 quit;
737 %put total records = &tot_obs.;
738 %if &tot_obs = 0 %then
739 %do;
740 proc datasets lib= work;
741 delete _LAF_SPCL_LIST_FILES_&laf_iteration_number;
742 quit;
743 %if lal_append_flag = 1 %then
744 %do;
745 data work._LAF_spcl_list_files_&laf_iteration_number.;
746 set work._LAF_spcl_list_files_&laf_iteration_number._inter;
747 run;
748 proc datasets lib= work;
749 delete _LAF_spcl_list_files_&laf_iteration_number._inter;
750 quit;
751 %end;
752 %end; %else
753 %do;
754 %if lal_append_flag = 1 %then
755 %do;
756 data work._LAF_spcl_list_files_&laf_iteration_number.;
757 set work._LAF_spcl_list_files_&laf_iteration_number.
758 work._LAF_spcl_list_files_&laf_iteration_number._inter;
759 run;
760 proc datasets lib= work;
761 delete _LAF_spcl_list_files_&laf_iteration_number._inter;
762 quit;
763 %end;
764 %end;
765
766 %if &laf_iteration_number = 0_0 %then
767 %do;
768 %let table_append_seq = ;
769 proc sql noprint;
770 select memname into :table_append_seq separated by " "
771 from dictionary.tables
772 where upcase(libname)='WORK' and
773 upcase(memname)contains"_LAF_SPCL_LIST_FILES_";
774 quit;
775 %if "&table_append_seq" ne "" %then
776 %do;
777 data work._laf_file_overview_sort;
778 set &table_append_seq;
779 run;
780 proc sort data =work._laf_file_overview_sort;
781 by full_file_name
782 %if &laf_include_directories = 1 %then
783 %do;
784 descending object_type
785 %end;
786 ;
787 quit;
788
789 data &laf_output_ds_file_overview;
790 set work._laf_file_overview_sort;
791 by full_file_name;
792 %if &laf_include_directories = 1 %then
793 %do;
794 if first.full_file_name ne last.full_file_name then
795 do;
796 object_type = "file";
797 end;
798 %end;
799 if first.full_file_name;
800 run;
801 %end;
802
803
804 %end;
805
806 %if &laf_do_processing = 1 %then
807 %do;
808 filename f&laf_iteration_number clear;
809 %end;
810 %mend list_all_files;
811 /** FOR TESTING ***
812
813
814 option mprint source notes;
815 %let root_directory = /Users/<<MYUSERID>>/My Folder/SAS Videos;
816 %let is_content_dir = 0;
817 %let delimiter = /;
818 %let delimiter = \;
819 %let include_directories = 1;
820 %let extension = *;
821 %let overview_ds = work.file_overview;
822 %let traverse_directories = 1;
823 %list_all_files(
824 &root_directory,
825 &extension,
826 &overview_ds,
827 laf_traverse_directories = &traverse_directories,
828 laf_debug_mode = 1,
829 laf_directory_separator = /,
830 laf_is_sas_content_directory = &is_content_dir,
831 laf_include_directories = &include_directories
832 );
833
834 *********************/
835 /******************************************************************************
836 %wordcnt
837 ________
838 Counts the words in a list
839 ______________________________________________________________________________
840
841 USAGE: %wordcnt(list,delim)
842 ______________________________________________________________________________
843
844 DESCRIPTION:
845
846 Finds the number of words/tokens in a string. The user specifies a
847 delimiter e.g. # to identify what separates the words. The macro should be
848 called in the following way:
849 e.g. %let x=%wordcnt(item1#item2 item2a#item3, '#').
850 After running the macro x will be assigned the value of wordcnt.
851 ______________________________________________________________________________
852
853 INPUT PARAMETERS AND KEYWORDS:
854
855 list the name of the string.
856 delim the delimiter e.g. '#'.
857 _________________________________________________________________________
858
859 CALLS: none.
860 ______________________________________________________________________________
861
862 NOTES: (Initials, date, summary)
863
864 Stephan Weigandt 20200406 First officially Released Version
865 ______________________________________________________________________________
866
867 *******************************************************************************/
868 %macro wordcnt(
869 list,
870 delim
871 )
872 ;
873 %local
874 word
875 wc_count;
876 %let wc_count = 0;
877 %if %quote(&list) ne %then
878 %do;
879 %let word = %scan(%quote(&list), 1, &delim);
880 %let word = %quote(&word);
881 %do %while (&word ne);
882 %let wc_count = %eval(&wc_count + 1);
883 %let word = %scan(%quote(&list), &wc_count+1, &delim);
884 %let word = %quote(&word);
885 %end;
886 %end;
887 &wc_count
888 %mend wordcnt;
889 /** FOR TESTING ***
890 option mprint source notes ;
891 %let item_seq = a b c#d$f g #h#i$j;
892 %let separator = '$' ;
893 %let separator = '#' ;
894 %let separator = ' ' ;
895 %let number_of_items = %wordcnt(&item_seq, &separator);
896 %put &=number_of_items;
897
898 *********************/
899 %macro execute_all();
900
901 %let write_log_to_file = &write_log_into_file_ui;
902 %if &write_log_to_file eq 1 %then
903 %do;
904 %let provide_default_log_path = %scan(&log_file_path_ui, 2, ":")/;
905 %let log_file_directory_source_ui = %scan(&log_file_path_ui, 1, ":");
906
907 %if "%upcase(&log_file_directory_source_ui)" eq "SASSERVER" %then
908 %do;
909 %let log_file_in_SAS_Content = 0;
910 %end; %else
911 %do;
912 %let log_file_in_SAS_Content = 1;
913 %end;
914
915 /**
916 determine and set todays date
917 **/
918 data _null_;
919 todaysdate = today();
920 year = year(todaysdate);
921 month = put(month(todaysdate), z2.);
922 day = put(day(todaysdate), z2.);
923 nowtime = time();
924 hour = put(hour(nowtime), z2.);
925 minute = put(minute(nowtime), z2.);
926 put minute;
927 timestamp = trim(left(year))||
928 trim(left(month))||
929 trim(left(day))||
930 "_"||
931 trim(left(hour))||
932 trim(left(minute));
933 call symput('timestamp', timestamp);
934 run;
935 %let timestamp = %trim(%left(×tamp));
936 %if &debug_mode_ui = 1 %then
937 %do;
938 %put INFORMATION: Logfile location: &provide_default_log_path;
939 %put INFORMATION: Logfile name : clod_run_×tamp..log;
940 %end;
941
942
943 %if &log_file_in_SAS_Content = 1 %then
944 %do;
945 filename logfl
946 filesrvc
947 folderpath = "&provide_default_log_path"
948 filename = "clod_run_×tamp..log";
949 filename printfl
950 filesrvc
951 folderpath = "&provide_default_log_path"
952 filename = "clod_run_×tamp..out";
953 %end; %else
954 %do;
955 filename logfl "&provide_default_log_path.clod_run_×tamp..log";
956 filename printfl "&provide_default_log_path.clod_run_×tamp..out";
957 %end;
958 proc printto
959 log=logfl new
960 print=printfl new;
961 quit;
962 %end;
963
964
965
966 %put &=debug_mode_ui ;
967 %put &=clod_traverse_directories_ui ;
968 %put &=extension_ui ;
969 %put &=root_directory_ui ;
970 %put &=log_file_path_ui;
971 %let target_libname_ui = &outputtable_ui_lib;
972 %let output_dataset_name_ui = &outputtable_ui_name;
973 %put &=target_libname_ui ;
974 %put &=write_log_into_file_ui ;
975 %put &=output_dataset_name_ui;
976 %put &=options_seq_ui;
977 %let root_directory = %scan(&root_directory_ui, 2, ":");
978 %let root_dir_src = %upcase(%scan(&root_directory_ui, 1, ":"));
979 %let is_content_dir = 0;
980 %if %upcase("&root_dir_src") eq "SASCONTENT" %then
981 %do;
982 %let is_content_dir = 1;
983 %end;
984 %put &=root_directory;
985
986 %let target_libname = &target_libname_ui ;
987 %let write_log_into_file = &write_log_into_file_ui ;
988
989
990 %let provide_default_log_path = ;
991 %let log_file_directory_source_ui = ;
992 %if "&log_file_path_ui" ne "" %then
993 %do;
994 %let provide_default_log_path = %scan(&log_file_path_ui, 2, ":")/;
995 %let log_file_directory_source_ui = %scan(&log_file_path_ui, 1, ":");
996 %end;
997 %if "%upcase(&log_file_directory_source_ui)" eq "SASSERVER" %then
998 %do;
999 %let install_mode_in_SAS_Content = 0;
1000 %end; %else
1001 %do;
1002 %let install_mode_in_SAS_Content = 1;
1003 %end;
1004 %let target_environment = ;
1005 proc sql noprint;
1006 select distinct(engine)
1007 into :target_environment
1008 from dictionary.libnames
1009 where upcase(libname) = "%upcase(&target_libname_ui)"
1010 ;
1011 quit;
1012
1013 %if %upcase(&target_environment) = CAS %then
1014 %do;
1015 %if &cas_promote_ui = 1 %then
1016 %do;
1017 proc casutil incaslib="&target_libname_ui"
1018 outcaslib="&target_libname_ui";
1019 droptable casdata = "&output_dataset_name_ui" quiet;
1020 droptable casdata = "&output_dataset_name_ui" quiet;
1021 quit;
1022 %end;
1023 %end;
1024
1025
1026 %let include_directories = 1;
1027 %let overview_ds = &target_libname_ui..&output_dataset_name_ui;
1028 %let traverse_directories = 1;
1029 %list_all_files(
1030 &root_directory,
1031 &extension_ui,
1032 &overview_ds,
1033 laf_traverse_directories = &clod_traverse_directories_ui,
1034 laf_debug_mode = &debug_mode_ui,
1035 laf_directory_separator = &clod_delimiter,
1036 laf_is_sas_content_directory = &is_content_dir,
1037 laf_include_directories = &include_directories_ui
1038 );
1039
1040 %if %upcase(&target_environment) = CAS %then
1041 %do;
1042 %if &cas_promote_ui = 1 %then
1043 %do;
1044 proc casutil incaslib="&target_libname_ui"
1045 outcaslib="&target_libname_ui";
1046 promote casdata = "&output_dataset_name_ui"
1047 casout="&output_dataset_name_ui";
1048 %if &cas_save_on_disk_ui = 1 %then
1049 %do;
1050 save casdata= "&output_dataset_name_ui"
1051 casout="&output_dataset_name_ui" replace;
1052 %end;
1053 quit;
1054
1055 %end;
1056
1057 %end;
1058
1059 %if &write_log_to_file = 1 %then
1060 %do;
1061 proc printto ;
1062 quit;
1063 %end;
1064
1065 %mend execute_all;
1066
1067 %execute_all();
DEBUG_MODE_UI=1
CLOD_TRAVERSE_DIRECTORIES_UI=0
EXTENSION_UI=*
ROOT_DIRECTORY_UI=sasserver:/mnt/viya-share/data/sas-studio-custom-steps
LOG_FILE_PATH_UI=
TARGET_LIBNAME_UI=WORK
WRITE_LOG_INTO_FILE_UI=0
OUTPUT_DATASET_NAME_UI=FILENAMES_NEW
OPTIONS_SEQ_UI=
ROOT_DIRECTORY=/mnt/viya-share/data/sas-studio-custom-steps
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
Directory
Libref WORK
Engine V9
Physical Name /opt/sas/viya/config/var/tmp/compsrv/default/42333e50-aa47-4021-a542-1c78ed1883c5/
SAS_work1C170000018D_sas-compute-server-63fcf1ec-796e-429b-8d19-78e8da61225b-3875
Filename /opt/sas/viya/config/var/tmp/compsrv/default/42333e50-aa47-4021-a542-1c78ed1883c5/
SAS_work1C170000018D_sas-compute-server-63fcf1ec-796e-429b-8d19-78e8da61225b-3875
Inode Number 5678008
Access Permission rwx------
Owner Name UNKNOWN
File Size 4KB
File Size (bytes) 4096
Member
# Name Type File Size Last Modified
1 FILENAMES DATA 128KB 28/08/2024 19:05:58
2 FILENAMES_NEW DATA 256KB 28/08/2024 19:00:58
3 PROFILE CATALOG 12KB 28/08/2024 18:03:14
4 REGSTRY ITEMSTOR 32KB 28/08/2024 18:03:14
5 SASGOPT CATALOG 12KB 28/08/2024 18:04:16
6 SASMAC3 CATALOG 20KB 28/08/2024 19:05:57
7 SASMACR CATALOG 240KB 28/08/2024 19:05:58
8 _AOSC_TEMP_OPTION_STORAGE_DS DATA 128KB 28/08/2024 19:05:58
NOTE: The file WORK._LAF_SPCL_LIST_FILES_: (memtype=DATA) was not found, but appears on a DELETE statement.
NOTE: PROCEDURE DATASETS used (Total process time):
real time 0.01 seconds
cpu time 0.02 seconds
INFORMATION: Found following file:/mnt/viya-share/data/sas-studio-custom-steps/CUSTOM_STEPS_LIST.md
INFORMATION: Found following file:/mnt/viya-share/data/sas-studio-custom-steps/SUPPORT.md
INFORMATION: Found following file:/mnt/viya-share/data/sas-studio-custom-steps/CONTRIBUTING.md
INFORMATION: Found following file:/mnt/viya-share/data/sas-studio-custom-steps/README.md
INFORMATION: Found following file:/mnt/viya-share/data/sas-studio-custom-steps/ContributorAgreement.txt
INFORMATION: Found following file:/mnt/viya-share/data/sas-studio-custom-steps/LICENSE
NOTE: The data set WORK._LAF_SPCL_LIST_FILES_0_0 has 6 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
total records = 6
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: There were 6 observations read from the data set WORK._LAF_SPCL_LIST_FILES_0_0.
NOTE: The data set WORK._LAF_FILE_OVERVIEW_SORT has 6 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: There were 6 observations read from the data set WORK._LAF_FILE_OVERVIEW_SORT.
NOTE: The data set WORK._LAF_FILE_OVERVIEW_SORT has 6 observations and 5 variables.
NOTE: PROCEDURE SORT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: There were 6 observations read from the data set WORK._LAF_FILE_OVERVIEW_SORT.
NOTE: The data set WORK.FILENAMES_NEW has 6 observations and 5 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: Fileref F0_0 has been deassigned.
1068
1069 /**
1070 Restore original SAS options settings
1071 **/
1072
1073 %adjust_option_setings_controlled(
1074 aosc_running_mode = RESET
1075 );
NOTE: There were 1 observations read from the data set WORK._AOSC_TEMP_OPTION_STORAGE_DS.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
NOTE: CALL EXECUTE generated line.
1 + option validvarname = ANY ;
1076
1077 %if &debug_mode_ui ne 1 %then
1078 %do;
1079 proc datasets lib=work;
1080 delete
1081 _clod:
1082 _LAF_:
1083 _aosc:
1084 ;
1085 quit;
1086 %end;
1087
1088
1089 /* SAS code provided in template section of Custom Step - END */
1090
1091 /* region: Generated macro cleanup */
1092
1093 /* Cleanup macros and macro variables - BEGIN */
1094 /* Delete macro variables created in this step */
1095
1096 %_flw_del_macro_vars( Extension_ui );
1097 %_flw_del_macro_vars( cas_promote_ui );
1098 %_flw_del_macro_vars( cas_save_on_disk_ui );
1099 %_flw_del_macro_vars( clod_traverse_directories_ui );
1100 %_flw_del_macro_vars( debug_mode_ui );
1101 %_flw_del_macro_vars( include_directories_ui );
1102 %_flw_del_macro_vars( log_file_path_ui );
1103 %_flw_del_macro_vars( options_seq_ui );
1104 %_flw_del_macro_vars( outputtable_ui outputtable_ui_engine outputtable_ui_label outputtable_ui_lib outputtable_ui_name
1104! outputtable_ui_name_base
1105 outputtable_ui_tblType outputtable_ui_type );
1106 %_flw_del_macro_vars( root_directory_ui );
1107 %_flw_del_macro_vars( write_log_into_file_ui );
1108 /* Delete macros defined in this step */
1109 %_flw_del_macros(_flw_get_column_list _flw_del_macro_vars);
1110
1111 /* Cleanup macros and macro variables - END */
1112
1113 %sysmacdelete _flw_del_macros;
1114
1115 /* endregion */
1116
1117
1118 /* region: Generated step cleanup for PY_SAS_Create Listing Of Directory CLOD */
1119 %_flw_action_end(id-1724871581560-7807, WORK.FILENAMES_NEW, WORK, "FILENAMES_NEW");
_FLW_ACTION_TABLE_|WORK|FILENAMES_NEW|1
_FLW_ACTION_END_|2024-08-28T15:05:58+00:00|id-1724871581560-7807
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
1120 /* endregion */
1121
1122 /* region: Generated sub flow cleanup for Obtain a list of all folders with custom steps */
1123 %_flw_action_end(id-1724868400470-1799,,,);
_FLW_ACTION_TABLE_|| |1
_FLW_ACTION_END_|2024-08-28T15:05:58+00:00|id-1724868400470-1799
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
1124 /* endregion */
1125
1126 /* region: Generated flow cleanup */
1127 %sysmacdelete _flw_action_start;
1128 %sysmacdelete _flw_action_end;
1129 /* endregion */
1130 /* region: Generated postamble */
1131
1132 /* Close ODS destinations */
1133 &graphterm; ;*';*";*/;run;quit;
1134 quit;run;
1135 ods html5 (id=web) close;
1136 ods listing close;
1137 %if %sysfunc(fileref(_gsfname)) lt 0 %then %do;
1138 filename _gsfname clear;
NOTE: Fileref _GSFNAME has been deassigned.
1139 %end;
1140
1141 /* endregion */
1142
1143
1144
Environment (please complete the following information):
Describe the bug Hi @stephanweigandt , I provide some screenshots with the parameters I changed. I explicitly selected Yes to "Include Directories in Output" and chose to list contents only at root level (traverse = No).
I noticed a debug mode and ran it with 1. Log is shown below. I see only the files printed, not the directories.
Note
My ideal output is to list only folders within a directory. But there's no option to say list only folders (directories) in output. This might be a feature request in addition to resolving this issue :).
To Reproduce Steps to reproduce the behavior: Plain vanilla run of custom step in a flow, with only change made to "Traverse subdirectories - No" and Include directories - Yes.
Expected behavior
I expected to see all files and directories as part of output. Repeating note above.
Screenshots Added shots of parameter choices and output.
Environment (please complete the following information):
Additional context Add any other context about the problem here.