ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

need help working with files on IFS

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • need help working with files on IFS

    Hi,
    as subj. says I need help working with files on IFS.

    I have a folder on IFS "/home/mydir"
    this folder is used to FTP files onto AS/400 for further processing,
    basically I get the file from FTP server and import them into database.
    the files are CSV type.

    I use CL to run FTP script to get the files in the folder and RPGLE program to import the data into appropriate PF/Tables as needed.

    the ftp script also generates the file list to describe what files will need to be processed. this is needed since I get 2 distinct file types in the process and each needs to be properly processed into PF.



    now I want to move all processed files into a sub-folder "/home/mydir/processed"

    currently as my RPG program processes the file it adds the record to a TXT member which is later used to create an FTP rename script
    that I use to move the files. I want to eliminate the FTP part and use native CL code to move this files

    how do I do that?

    the idea is that after I process all data into PF I can use the same file list I used for processing to move the files into sub-folder.

    right now I do that by building and the ftp script based on the list and than calling a CL with the script as input. can I simply read the file list in the CL and build a move command for each entry?

    OR
    can I get the dir listing with in the CL based on wild card and use the output in a loop to build a move command?


    PS: if I can get the IFS dir list within RPGLE program and used that for processing it would also help streamline the process.


    thanks

  • #2
    Re: need help working with files on IFS

    Sure - you can move the files from CL using the MOV command.

    You can read a file from CL using the DCLF and RCVF commands.

    You can generate a file of directory contents using the RTVDIRINF command (*PUBLIC authority to the command is *EXCLUDE).

    Cheers,

    Emmanuel

    Comment


    • #3
      Re: need help working with files on IFS

      Scott Klement has a tutorial and examples here http://www.scottklement.com/rpg/ifs.html that show how to use the IFS in RPGLE. I use it all the time to do exactly what you want to do.

      Comment


      • #4
        Re: need help working with files on IFS

        Here's a sample ILE CL program that accepts a directory name as input, reads the entries from the directory, and sends messages telling if the entry was created before or after 7 days ago:
        Code:
        /* +
           Open a supplied directory, read each directory entry, determine create +
           date, note entries more than seven days old.                           +
                                                                                  +
           Subrs:                                                                 +
              InitDirDta - Initialize directory request data                      +
              OutEntry   - Send result messages for each entry                    +
              GetErrNo   - Retrieve any errno from APIs                           +
              Get_7Days  - Date seven days before today                           +
                                                                                  +
           APIs:                                                                  +
              opendir     - Open directory for reading entries                    +
              readdir     - Read next entry from directory                        +
              closedir    - Close the directory when done                         +
              Qp0lGetAttr - Get an attribute of a directory entry                 +
              ctime       - Convert data/time to string                           +
              __errno     - Pull errno from internal space                        +
              strerrno    - Get pointer to error string                           +
              strlen      - Get length of (null term) string                      +
              triml       - Get length of (null term) string if right blanks      +
              time        - Get current time as internal format                   +
                                                                                  +
        */
        
        pgm    ( +
                 &DirName     +
               )
        
           dcl   &DirName     *char   256
        
        
           dcl   &FName       *char   640
        
           dcl   &rc          *int
           dcl   &subrc       *int
           dcl   &rtnrc       *int
        
           dcl   &Dir         *char   512
        
           dcl   &t1          *int
        
           dcl   &@CTime      *ptr
           dcl   &CTime       *char    24     stg( *BASED ) basptr( &@CTime )
        
           dcl   &@Dir        *ptr
        
         /* Directory entry DS */
           dcl   &@DirEnt     *ptr
           dcl   &DirEnt      *char  1024     stg( *BASED ) basptr( &@DirEnt )
           dcl   &snamlen     *uint           stg( *defined ) defvar( &DirEnt 53 )
           dcl   &sfname      *char   640     stg( *defined ) defvar( &DirEnt 57 )
        
           dcl   &szProv      *uint     4     value( 0 )
           dcl   &szNeed      *uint     4     value( 0 )
           dcl   &szRtn       *uint     4     value( 0 )
        
           dcl   &lPath       *int            value( 0 )
        
           dcl   &pathBuffer  *char  1185
           dcl    &CCSID      *int      4     stg( *defined ) defvar( &pathBuffer 1 )
           dcl    &RegionID   *char     2     stg( *defined ) defvar( &pathBuffer 5 )
           dcl    &LanguageID *char     3     stg( *defined ) defvar( &pathBuffer 7 )
           dcl    &Reserved1  *char     3     stg( *defined ) defvar( &pathBuffer 10 )
           dcl    &pathType   *int      4     stg( *defined ) defvar( &pathBuffer 13 )
           dcl    &lpathName  *int      4     stg( *defined ) defvar( &pathBuffer 17 )
           dcl    &pathDlmtr  *char     2     stg( *defined ) defvar( &pathBuffer 21 )
           dcl    &Reserved2  *char    10     stg( *defined ) defvar( &pathBuffer 23 )
           dcl    &pathNameIn *char  1153     stg( *defined ) defvar( &pathBuffer 33 )
        
        /* For Qp0lGetAttrNo attribute request and returned value  */
        
           dcl   &attrTypes   *char     8
           dcl    &attrNbrReq *uint     4     stg( *defined ) defvar( &attrTypes  1 )
           dcl    &attrReqstd *uint     4     stg( *defined ) defvar( &attrTypes  5 )
        
           dcl   &rtnBuffOvl  *char    32
           dcl    &rtnAttrDta *char    16     stg( *defined ) defvar( &rtnBuffOvl 17 )
           dcl     &crttime   *int            stg( *defined ) defvar( &rtnAttrDta  1 )
        
        /* For SUBR GetErrNo   */
        
           dcl   &@errno      *ptr
           dcl   &@strerror   *ptr
        
           dcl   &errno       *int            stg( *BASED ) basptr( &@errno )
           dcl   &strerror    *char   257     stg( *BASED ) basptr( &@strerror )
           dcl   &szErrStr    *int            value( 1 )
           dcl   &errstr      *char   257     value( ' ' )
        
        /* Indicate end-of-program   */
        
           dcl   &eoPgm       *lgl            value( '0' )
        
        /* Some constants   */
        
           dcl   &ATTRCRTTIM  *int            value( 4 )  /* QP0L_ATTR_CREATE_TIME */
           dcl   &SECSPERDAY  *int            value( 86400 )
           dcl   &SYMLINK     *uint     4     value( 1 )
           dcl   &X00         *char     1     value( x'00' )
        
        /* Null pointer for comparison   */
        
           dcl   &NULLPTR     *ptr
        
        
           monmsg    ( cpf0000 mch0000 cpf9999 ) exec( goto StdErr )
        
        
           callsubr    InitDirDta   rtnval( &subrc )
        
        
           callprc     'opendir'          ( &Dir ) rtnval( &@Dir )
        
           if ( &@Dir *ne &NULLPTR )  do
        
              dountil  ( &@DirEnt *eq &NULLPTR )
        
                 callprc     'readdir'       ( (&@Dir *byval) ) ( &@DirEnt )
                 if ( &@DirEnt *ne &NULLPTR )  +
                    callsubr    OutEntry     rtnval( &subrc )
        
              enddo
        
           enddo
        
           chgvar      &eoPgm             ( '1' )
        
        
        StdErr:
        
           if ( *not &eoPgm )  do
              dmpclpgm
              monmsg (cpf0000 cpf9999 mch0000)
           endDo
        
        Close_Dir:
        
           callprc     'closedir'         ( (&@Dir *byval) ) rtnval( &rc )
           monmsg (cpf0000 cpf9999 cee0000 mch0000)
        
           return
        
        /* +
           Output messages noting older than seven days or not                    +
        */
        
        subr     OutEntry
        
           if ( &snamlen *gt 0 )  do
        
              chgvar         &FName   %sst( &sfname 1 &snamlen )
        
            /* Ignore '.' and '..' entries... */
              if ( &FName *ne '.' *and &FName *ne '..' )  do
        
                 chgvar      &lpathName         ( &lPath + 1 + &snamlen )
                 chgvar      &pathNameIn        ( +
                                                  &DirName *tcat '/' *cat +
                                                  &FName   *tcat +
                                                  &X00  +
                                                )
               /* Get create-date of this entry... */
                 callprc  'Qp0lGetAttr'   ( +
                                            &pathBuffer  +
                                            &attrTypes   +
                                            &rtnBuffOvl  +
                                            ( &szProv *byval )     +
                                            &szNeed      +
                                            &szRtn       +
                                            ( &SYMLINK *byval )    +
                                          ) +
                                    rtnval( &rc       )
                 if ( &rc *eq 0 )  do
        
                  /* Convert time value to string for message... */
                    callprc  'ctime'         ( &crttime ) rtnval( &@CTime )
        
                  /* Note create date/time of entry... */
                    sndpgmmsg   msgid( CPF9898 ) msgf( QCPFMSG ) +
                                  msgdta( +
                                          'Object Found'   *bcat +
                                          &CTime           *bcat +
                                          &FName                 +
                                        ) +
                                  msgtype( *INFO )
        
                  /* Send message depending on too old or not... */
                    if ( &crttime *lt &t1 )  do
                       sndpgmmsg   msgid( CPF9898 ) msgf( QCPFMSG ) +
                                  msgdta( +
                                          'Aged too old:'  *bcat +
                                          &FName                 +
                                        ) +
                                  msgtype( *INFO )
                    enddo
                    else  do
                       sndpgmmsg   msgid( CPF9898 ) msgf( QCPFMSG ) +
                                  msgdta( +
                                          'Recent file:'   *bcat +
                                          &FName                 +
                                        ) +
                                  msgtype( *INFO )
                    enddo
                    chgvar   &rtnrc       ( 0 )
                 enddo
        
               /* In case of error, report error... */
                 else  do
                    callsubr GetErrNo
                    chgvar   &rtnrc             ( -1 )
                 enddo
        
              enddo
        
           enddo
        
           rtnsubr rtnval( &rtnrc )
        
           endsubr
        
        /* -------------------  */
        
        /* +
           Get any current API error message                                      +
        */
        
           subr  GetErrNo
        
           callprc     '__errno'    rtnval( &@errno )
        
           callprc     'strerror'         ( +
                                            ( &errno   *byval ) +
                                          ) +
                                    rtnval( &@strerror )
        
           callprc     'strlen'           ( &strerror ) rtnval( &szErrStr )
        
           chgvar            &errstr        %sst( &strerror 1 &szErrStr )
        
           rtnsubr rtnval( 0 )
        
           endsubr
        
        /* -------------------  */
        
        /* +
           Initialize structures for opening directory and 7-days date/time       +
        */
        
           subr  InitDirDta
        
           chgvar            &Dir               ( &DirName *tcat &X00 )
        
         /* Trim to find length (could use 'strlen' instead)... */
           callprc  'triml'  ( +
                               &Dir         +
                               ( ' '   *byval ) +
                             ) +
                       rtnval( &lPath )
        
           chgvar            &CCSID             ( 0 )
           chgvar            &RegionID          ( x'0000' )
           chgvar            &LanguageID        ( x'000000' )
           chgvar            &Reserved1         ( x'000000' )
           chgvar            &pathType          ( 0 )
           chgvar            &lpathName           &lPath
           chgvar            &pathDlmtr           '/'
           chgvar            &Reserved2         ( x'00000000000000000000' )
        
           chgvar            &attrNbrReq        ( 1 )
           chgvar            &attrReqstd        ( &ATTRCRTTIM )
        
           chgvar            &szProv            ( 32 )
           chgvar            &szNeed            ( 0 )
           chgvar            &szRtn             ( 0 )
        
           callsubr    Get_7Days    rtnval( &subrc )
        
           rtnsubr rtnval( 0 )
        
           endsubr
        
        /* -------------------  */
        
        /* +
           Calculate date/time value for seven days ago                           +
        */
        
           subr  Get_7Days
        
         /* Determine current time... */
           callprc  'time'      ( +
                                  &NULLPTR     +
                                ) +
                          rtnval( &t1 )
        
         /* Subtract 7 days from date/time integer value... */
           chgvar            &t1                ( &t1 - ( &SECSPERDAY * 7 ))
        
           rtnsubr rtnval( 0 )
        
           endsubr
        
        /* -------------------  */
        
        endpgm
        Note that the input parm needs to account for the declared CHAR(256) length. If you call from a command line, pad the parm with blanks out to at least 256 characters to avoid memory garbage. Also note that it requires at least V5R4 to compile.

        It's not a fully functional process. It's only some code I used a few years ago for some testing. But it might demonstrate enough APIs to show you how to do what you want.
        Tom

        There are only two hard things in Computer Science: cache invalidation, naming things and off-by-one errors.

        Why is it that all of the instruments seeking intelligent life in the universe are pointed away from Earth?

        Comment


        • #5
          Re: need help working with files on IFS

          Most commands that use the /Root naming convention simply don't have OBJ on the end (RNMOBJ becomes RNM etc etc). If you want to move your file to another directory after processing it, try the MOV command. I assume your RPG program knows the file name so could just issue the MOV once it's finished processing the file which might be simpler than building/maintaining a list of files to move later.

          Comment


          • #6
            Re: need help working with files on IFS

            Even easier than the methods described here would be to use a shell script, such as QShell. Is that a possiblity for you?

            Code:
            QSH CMD('cd /home/mydir; for f in *.*; do mv $f ./processed; done')

            Comment


            • #7
              Re: need help working with files on IFS

              thanks for all your help.
              I made it working with "MOV OBJ(&FRMPATH) TODIR(&TOPATH) "
              command in CL.
              I call all the processing apps first. than call pgm to upload the file to FTP
              and if it is successful (using return parm)
              I call the MOV cmd

              works perfect

              Comment

              Working...
              X