subroutine complete_list(folder_in, & Nfolders_out,folders_out,Nfiles_out,files_out) implicit none include 'max.inc' c c Purpose: to get the complete list of all sub-folders and all files c from an initial folder. c c Inputs: c + folder_in: input folder (whose content has to be listed) c c Outputs: c + Nfolders_out: number of folders that reside within the input folder c + folders_out: names of the folders that reside within the input folder c + Nfiles_out: number of files that reside within the input folder c + files_out: names of the files that reside within the input folder c c I/O character*(Nchar_mx) folder_in integer Nfolders_out,Nfiles_out character*(Nchar_mx) folders_out(1:Nf_mx) character*(Nchar_mx) files_out(1:Nf_mx) c temp integer cf,j character*(Nchar_mx) tfolder_in integer tNfolders_out,tNfiles_out character*(Nchar_mx) tfolders_out(1:Nf_mx) character*(Nchar_mx) tfiles_out(1:Nf_mx) integer strlen character*(Nchar_mx) label label='subroutine complete_list' cf=0 tfolder_in=folder_in(1:strlen(folder_in)) call base_list(tfolder_in, & tNfolders_out,tfolders_out,tNfiles_out,tfiles_out) Nfolders_out=0 Nfiles_out=0 call add_temp(tNfolders_out,tfolders_out,tNfiles_out,tfiles_out, & Nfolders_out,folders_out,Nfiles_out,files_out) c Debug c write(*,*) 'Nfolders_out=',Nfolders_out c do j=1,Nfolders_out c write(*,*) 'folders_out(',j,')=', c & folders_out(j)(1:strlen(folders_out(j))) c enddo ! j c Debug do while (cf.lt.Nfolders_out) cf=cf+1 tfolder_in=folders_out(cf)(1:strlen(folders_out(cf))) c Debug c write(*,*) 'cf=',cf,tfolder_in(1:strlen(tfolder_in)) c Debug call base_list(tfolder_in, & tNfolders_out,tfolders_out,tNfiles_out,tfiles_out) call add_temp(tNfolders_out,tfolders_out, & tNfiles_out,tfiles_out, & Nfolders_out,folders_out,Nfiles_out,files_out) c Debug c write(*,*) 'cf=',cf,' Nfolders_out=',Nfolders_out c Debug enddo return end subroutine add_temp(tNfolders,tfolders,tNfiles,tfiles, & Nfolders,folders,Nfiles,files) implicit none include 'max.inc' c c Purpose: to add temporary folders and files to the complete list c of folders and files c c Inputs: c + tNfolders: temporary number of folders c + tfolders: temporary list of folders c + tNfiles: temporary number of files c + tfiles: temporary list of files c c I/O: c + Nfolders: total number of folders (has to be updated) c + folders: complete list of folders (has to be updated) c + Nfiles: total number of files (has to be updated) c + files: complete list of files (has to be updated) c c I/O integer tNfolders,tNfiles character*(Nchar_mx) tfolders(1:Nf_mx) character*(Nchar_mx) tfiles(1:Nf_mx) integer Nfolders,Nfiles character*(Nchar_mx) folders(1:Nf_mx) character*(Nchar_mx) files(1:Nf_mx) c temp integer cf integer strlen character*(Nchar_mx) label label='subroutine add_temp' do cf=1,tNfolders Nfolders=Nfolders+1 if (Nfolders.gt.Nf_mx) then call error(label) write(*,*) 'Nfolders reached Nf_mx' stop else folders(Nfolders)=tfolders(cf)(1:strlen(tfolders(cf))) endif enddo ! cf do cf=1,tNfiles Nfiles=Nfiles+1 if (Nfiles.gt.Nf_mx) then call error(label) write(*,*) 'Nfiles reached Nf_mx' stop else files(Nfiles)=tfiles(cf)(1:strlen(tfiles(cf))) endif enddo ! cf return end subroutine base_list(folder_in, & Nfolders_out,folders_out,Nfiles_out,files_out) implicit none include 'max.inc' include 'mpif.h' c c Purpose: to list all folders and files in a given folder c c Inputs: c + folder_in: input folder (whose content has to be listed) c c Outputs: c + Nfolders_out: number of folders that reside within the input folder c + folders_out: names of the folders that reside within the input folder c + Nfiles_out: number of files that reside within the input folder c + files_out: names of the files that reside within the input folder c c I/O character*(Nchar_mx) folder_in integer Nfolders_out,Nfiles_out character*(Nchar_mx) folders_out(1:Nf_mx) character*(Nchar_mx) files_out(1:Nf_mx) c temp integer islink,file,folder character*(Nchar_mx) ref,link,path integer exist character*(Nchar_mx) command,line character*(Nchar_mx) list_file,nlines_file integer nl,l,islash integer Nquotes integer positions(1:Nquotes_mx) c Debug integer i integer ierr,pindex c Debug integer strlen character*(Nchar_mx) label label='subroutine base_list' c Get 'pindex', the index of the current process call MPI_COMM_RANK(MPI_COMM_WORLD,pindex,ierr) c Debug c write(*,*) 'pindex=',pindex c Debug call inquire_folder(folder_in,exist) if (exist.eq.0) then call error(label) write(*,*) 'Folder does not exist:' write(*,*) folder_in(1:strlen(folder_in)) stop endif list_file='./list.txt' call add_slash_if_absent(folder_in) c l: list files c B: do not list implied entries ending with tilde c A: almost all (do not list . and ..) c p: append / indicator to directories c Q: enclose entry names in double quotes c c update 11/01/2011: c MacOS version of 'ls' does not accept the -Q option; I had to c install the "fileutils" package from fink in order to enable c the unix-like version of 'ls' c c update 01/11/2012: c On MacOS 10.7.5, I had to install "coreutils" instead of "fileutils", c and then add /sw/lib/coreutils/bin to the path c command='/sw/lib/coreutils/bin/ls -lBApQ ' & //folder_in(1:strlen(folder_in)) & //' > ' & //list_file(1:strlen(list_file)) call exec(command) c Debug c write(*,*) 'ok1' c Debug nlines_file='./nlines' call get_nlines(list_file,pindex,nl) c Debug c write(*,*) 'nl=',nl c Debug Nfolders_out=0 Nfiles_out=0 open(16,file=list_file(1:strlen(list_file))) do l=1,nl read(16,'(a)') line c Debug c write(*,*) 'line=',line(1:strlen(line)) c Debug 111 continue call find_quotes(line,Nquotes,positions) c Debug c write(*,*) 'l=',l,' Nquotes=',Nquotes c do i=1,Nquotes c write(*,*) 'positions(',i,')=',positions(i) c enddo c Debug islink=0 if (Nquotes.ne.0) then if (Nquotes.eq.4) then ! most probably a symbolic link call is_link(folder_in,line,islink,file,folder,link,ref) c Debug c write(*,*) 'islink=',islink c write(*,*) 'link=',link(1:strlen(link)) c Debug if (islink.eq.1) then if (((file.eq.1).and.(folder.eq.0)).or. & ((file.eq.0).and.(folder.eq.1))) then path=link(1:strlen(link)) goto 222 else call error(label) write(*,*) 'running "is_link" on line=' write(*,*) line(1:strlen(line)) write(*,*) 'results are inconsistent:' write(*,*) 'file=',file write(*,*) 'folder=',folder stop endif else call error(label) write(*,*) 'Number of quotes in line=' write(*,*) line(1:strlen(line)) write(*,*) 'contains Nquotes=',Nquotes,' quotes' write(*,*) 'but result of "is_link" is:' write(*,*) 'islink=',islink stop endif ! islink=1 endif if (Nquotes.ne.2) then call error(label) write(*,*) 'line analyzed is:' write(*,*) line write(*,*) 'Number of quotes=',Nquotes stop else call detect_slash_at_end(line,islash) path=line(positions(1)+1:positions(2)-1) if (islash.eq.1) then folder=1 file=0 else folder=0 file=1 endif endif 222 continue c Debug c write(*,*) 'path=',path(1:strlen(path)) c write(*,*) 'folder=',folder,' file=',file c write(*,*) 'islink=',islink c Debug if ((folder.eq.1).and.(file.eq.0)) then Nfolders_out=Nfolders_out+1 if (Nfolders_out.gt.Nf_mx) then call error(label) write(*,*) 'Nfolders_out reached Nf_mx' stop else if (islink.eq.0) then folders_out(Nfolders_out)= & folder_in(1:strlen(folder_in)) & //path(1:strlen(path)) else folders_out(Nfolders_out)=path(1:strlen(path)) endif endif c Debug c write(*,*) 'folders_out(',Nfolders_out,')=', c & folders_out(Nfolders_out) c & (1:strlen(folders_out(Nfolders_out))) c stop c Debug else if ((folder.eq.0).and.(file.eq.1)) then Nfiles_out=Nfiles_out+1 if (Nfiles_out.gt.Nf_mx) then call error(label) write(*,*) 'Nfiles_out reached Nf_mx' stop else if (islink.eq.0) then files_out(Nfiles_out)= & folder_in(1:strlen(folder_in)) & //path(1:strlen(path)) else files_out(Nfiles_out)=path(1:strlen(path)) endif endif c Debug c write(*,*) 'files_out(',Nfiles_out,')=', c & files_out(Nfiles_out) c & (1:strlen(files_out(Nfiles_out))) c stop c Debug else call error(label) write(*,*) 'inconsistency between:' write(*,*) 'file=',file write(*,*) 'folder=',folder stop endif endif ! Nquotes.ne.0 enddo ! line close(16) return end subroutine is_link(folder_in,line,islink,file,folder,link,ref) implicit none include 'max.inc' c c Purpose: to detect symbolic links within lines returned by the "ls" command c c Inputs: c + folder_in: folder the supposed link has been found in c + line: output from the "ls" command c c Outputs: c + islink: 1 if "line" contains a symbolic link; 0 otherwise c + file: in the case a link exists, file=1 if the link refers to a file c + folder: in the case a likn exists, folder=1 if the link refers to a folder c + link: symbolic link c + ref: path to the file or folder refered by the link c I/O character*(Nchar_mx) folder_in,line integer islink,file,folder character*(Nchar_mx) link,ref c temp character*1 sstring logical ex integer ios,exist integer n,i,af,position,Nquotes integer positions(1:Nquotes_mx) character*(Nchar_mx) path character*2 arrow integer strlen character*(Nchar_mx) label label='subroutine is_link' sstring='/' c looking for "->" arrow='->' n=strlen(line) af=0 position=0 do i=1,n-1 if (line(i:i+1).eq.arrow(1:2)) then af=1 position=i goto 123 endif enddo ! i 123 continue if (af.eq.1) then islink=1 else islink=0 endif if (islink.eq.1) then call find_quotes(line,Nquotes,positions) if (Nquotes.ne.4) then call error(label) write(*,*) 'line=',line(1:strlen(line)) write(*,*) 'Number of quotes=',Nquotes write(*,*) 'symbolic link was detected' stop endif path=folder_in(1:strlen(folder_in)) & //line(positions(1)+1:positions(2)-1) ref=line(positions(3)+1:positions(4)-1) c analyse of "ref" if (ref(1:1).ne.sstring(1:strlen(sstring))) then ref=folder_in(1:strlen(folder_in)) & //ref(1:strlen(ref)) endif open(13,file=path(1:strlen(path)) & ,status='old',iostat=ios) c Debug c write(*,*) 'folder_in=',folder_in(1:strlen(folder_in)) c write(*,*) 'path=',path(1:strlen(path)) c write(*,*) 'ios=',ios c stop c Debug if (ios.ne.0) then ! file not found file=0 folder=1 else file=1 folder=0 endif close(13) c Debug c write(*,*) 'file=',file c write(*,*) 'folder=',folder c write(*,*) 'ref=',ref(1:strlen(ref)) c stop c Debug if ((folder.eq.1).and.(file.eq.0)) then ! if folder detected call inquire_folder(ref,exist) if (exist.eq.0) then call error(label) write(*,*) 'ref=',ref(1:strlen(ref)) write(*,*) 'was identified as a folder' write(*,*) 'but access could not be granted' stop else link=path(1:strlen(path)) goto 666 endif endif if ((folder.eq.0).and.(file.eq.1)) then ! if file detected inquire(file=ref(1:strlen(ref)),exist=ex) c Debug c write(*,*) 'ex=',ex c Debug if (.not.ex) then call error(label) write(*,*) 'ref=',ref(1:strlen(ref)) write(*,*) 'was identified as a file' write(*,*) 'but inquire failed on it' stop else link=path(1:strlen(path)) goto 666 endif endif endif 666 continue c Debug c write(*,*) 'path=',path(1:strlen(path)) c write(*,*) 'file=',file c write(*,*) 'folder=',folder c write(*,*) 'link=',link(1:strlen(link)) c stop c Debug return end subroutine inquire_folder(folder,exist) implicit none include 'max.inc' c c Purpose: to detect whether the input folder exists or not c c Inputs: c + folder: character string that contains the folder path to test c c Outputs: c + exist: 1 if the folder exists, 0 otherwise c c I/O character*(Nchar_mx) folder integer exist c temp character*(Nchar_mx) command character*(Nchar_mx) dt_file character*(Nchar_mx) local_dir integer ios,lc_status integer strlen character*(Nchar_mx) label label='subroutine inquire_folder' dt_file='./local' command='pwd > ' & //dt_file(1:strlen(dt_file)) call exec(command) open(14,file=dt_file(1:strlen(dt_file)) & ,status='old',iostat=ios) if (ios.ne.0) then ! file not found call error(label) write(*,*) 'file not found:' write(*,*) dt_file(1:strlen(dt_file)) stop else read(14,'(a)') local_dir call add_slash_if_absent(local_dir) endif close(14) c Debug c write(*,*) 'folder=',folder(1:strlen(folder)) c write(*,*) 'local_dir=',local_dir(1:strlen(local_dir)) c stop c Debug dt_file='./status' command='cd ' & //folder(1:strlen(folder)) & //'; echo $? > ' & //local_dir(1:strlen(local_dir)) & //dt_file(1:strlen(dt_file)) c Debug c write(*,*) 'command=' c write(*,*) command(1:strlen(command)) c stop c Debug call exec(command) open(15,file=dt_file(1:strlen(dt_file)) & ,status='old',iostat=ios) if (ios.ne.0) then ! file not found call error(label) write(*,*) 'file not found:' write(*,*) dt_file(1:strlen(dt_file)) stop else read(15,*) lc_status endif close(15) if (lc_status.eq.0) then ! directory exists exist=1 else exist=0 endif return end subroutine detect_slash_at_end(line,islash) implicit none include 'max.inc' c c Purpose: to detect a slash character '/' at the end of c a given character string c c Inputs: c + line: character string to analyse c c Outputs: c + islash: 1 if the last character of "line" is a slash; 0 otherwise c c I/O character*(Nchar_mx) line integer islash c temp integer n character*1 sstring integer strlen character*(Nchar_mx) label label='subroutine detect_slash_at_end' sstring='/' n=strlen(line) if (line(n:n).eq.sstring(1:strlen(sstring))) then islash=1 else islash=0 endif return end subroutine find_quotes(line,Nquotes,positions) implicit none include 'max.inc' c c Purpose: to find quote characters '"' within a character string c c Inputs: c + line: character string to analyse c c Outputs: c + Nquotes: number of quote characters found in the "line" string c + positions: positions of the quote characters c c I/O character*(Nchar_mx) line integer Nquotes integer positions(1:Nquotes_mx) c temp integer i,n character*1 qstring integer strlen character*(Nchar_mx) label label='subroutine find_quotes' qstring='"' Nquotes=0 n=strlen(line) c Debug c write(*,*) 'line=',line(1:strlen(line)) c write(*,*) 'n=',n c Debug do i=1,n if (line(i:i).eq.qstring(1:strlen(qstring))) then Nquotes=Nquotes+1 positions(Nquotes)=i endif enddo ! i return end