OS/2, eCS & ArcaOS - Technical > Utilities

Find missing files

<< < (2/2)

John Hollemans:
_____
Hello

The easiest wat yo find your files is to use a "standard" DIR command like this:
"DIR C:\1000*.PDF /S"

You may use the "*" to generalise the search more if you like.  This command is found in the HELP pages fir the DIR command.  I fins that it is extremely fast.  If the list is of found files is very long, just use the "less" command like this:
"DIR C:\1000*.PDF /S | less"

Regards / John

Lars:
You will need a REXX script. Use the "dir" command with the filename sorting option and pipe the command output into RXQUEUE. Then, set a counter to 1 and then, going through all files, construct an expected filename from the counter value and compare to real filename. If no match, issue warning. Increase counter by one and go to next file.

Andreas Schnellbacher:
Here's my script, roughly tested:


--- Code: ---/****************************************************************************
* findmissingfilenames.cmd
*
* Version: 2024-04-21
*
* Syntax: findmissingfilenames <filemask> <startnum> <endnum> [<logfile>]
*
* o  <filemask> must have a part with '???' chars, where the amount of it
*    depends on the range <startnum> to <endnum>.
* o  <filemask> may include a path.
* o  <startnum> and <endnum> must be numbers.
* o  <logfile> may optionally be specified. The default <logfile> is
*    'missing.log'.
* o  Every arg may be surrounded with double quotes.
*
* Examples:
*    findmissingfilenames 1????.pdf 1 500
*    findmissingfilenames 10???.pdf 1 500
*
* By Andreas Schnellbacher
****************************************************************************/
/* Some header lines are used as help text */
HelpStartLine = 6
HelpEndLine   = 18

'@ECHO OFF'
CALL SETLOCAL

/* ----------------- Standard CMD initialization follows ----------------- */
SIGNAL ON HALT NAME Halt
SIGNAL ON NOVALUE NAME RexxError
SIGNAL ON SYNTAX NAME RexxError
SIGNAL ON FAILURE NAME RexxError
/*
SIGNAL ON ERROR NAME RexxError     /* Causes doubled error messages */
SIGNAL ON NOTREADY NAME RexxError  /* Causes error at encoding */
*/

env   = 'OS2ENVIRONMENT'
TRUE  = (1 = 1)
FALSE = (0 = 1)
CrLf  = '0d0a'x
Redirection = '>NUL 2>&1'
PARSE SOURCE . . ThisFile
GlobalVars = 'env TRUE FALSE CrLf Redirection ERROR. ThisFile'

/* Some OS/2 Error codes */
ERROR.NO_ERROR           =   0
ERROR.INVALID_FUNCTION   =   1
ERROR.FILE_NOT_FOUND     =   2
ERROR.PATH_NOT_FOUND     =   3
ERROR.ACCESS_DENIED      =   5
ERROR.NOT_ENOUGH_MEMORY  =   8
ERROR.INVALID_FORMAT     =  11
ERROR.INVALID_DATA       =  13
ERROR.NO_MORE_FILES      =  18
ERROR.WRITE_FAULT        =  29
ERROR.READ_FAULT         =  30
ERROR.SHARING_VIOLATION  =  32
ERROR.GEN_FAILURE        =  31
ERROR.INVALID_PARAMETER  =  87
ERROR.ENVVAR_NOT_FOUND   = 204

rc = ERROR.NO_ERROR

CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
CALL SysLoadFuncs
/* ----------------- Standard CMD initialization ends -------------------- */

GlobalVars = GlobalVars 'rc LogFile HelpStartLine HelpEndLine'

DO once = 1 TO 1

   DefaultLogFile = 'missing.log'

   /* Parse args */
   PARSE ARG Args
   Args = STRIP( Args)
   
   /* Show help */
   IF Args = '' THEN
      CALL ShowHelp
   ELSE
   DO
      IF WORDPOS( Args, '-? /?') > 0 THEN
         CALL ShowHelp
   END     
   
   /* Parse and check arg words */
   rest = Args
   LogFile = ''
   a = 0
   DO WHILE rest <> ''
      a = a + 1
      rest = STRIP( rest)
      IF LEFT( rest, 1) = '"' THEN
         PARSE VAR rest '"'next'"' rest
      ELSE
         PARSE VAR rest next rest
      SELECT
         WHEN a = 1 THEN
         DO
            FileMask = next
            IF FileMask = '' THEN
            DO
               rc = ERROR.INVALID_PARAMETER
               CALL ExitError 'Error: filemask not specified.'
            END
         END
         WHEN a = 2 THEN
         DO
            StartNum = next
            IF StartNum = '' THEN
            DO
               rc = ERROR.INVALID_PARAMETER
               CALL ExitError 'Error: startnum not specified.'
            END
            IF DataType( StartNum) <> 'NUM' THEN
            DO
               rc = ERROR.INVALID_PARAMETER
               CALL ExitError 'Error: startnum is not a number.'
            END
         END
         WHEN a = 3 THEN
         DO
            EndNum = next
            IF EndNum = '' THEN
            DO
               rc = ERROR.INVALID_PARAMETER
               CALL ExitError 'Error: endnum not specified.'
            END
            IF DATATYPE( EndNum) <> 'NUM' THEN
            DO
               rc = ERROR.INVALID_PARAMETER
               CALL ExitError 'Error: endnum is not a number.'
            END
         END
         WHEN a = 4 THEN
            LogFile = next
      OTHERWISE
         rc = ERROR.INVALID_PARAMETER
         CALL ExitError 'Error: Too many args specified.'
      END
   END
   IF LogFile = '' THEN
      LogFile = DefaultLogFile
     
   /* Find number of contiguous '?' chars in FileMask */
   NumPartLen = 0
   NumPartPos = 0
   pStart = 1
   PrevChar = '?'
   DO n = 1 TO LENGTH( FileMask)
      ThisChar = SUBSTR( FileMask, n, 1)
      IF ThisChar <> '?' THEN
         ITERATE
      IF PrevChar <> '?' THEN
         LEAVE
      /* Save pos of first '?' char */   
      IF NumPartLen = 0 THEN   
         NumPartPos = n
      /* Advance length */   
      NumPartLen = NumPartLen + 1
      PrevChar = ThisChar
   END   
   
   /* Check number of contiguous '?' chars in FileMask */
   IF NumPartLen < LENGTH( StartNum) THEN
   DO
      rc = ERROR.INVALID_PARAMETER
      CALL ExitError 'Error: Number of ''?'' chars in filemask too low for startnum.'
   END
   IF NumPartLen < LENGTH( EndNum) THEN
   DO
      rc = ERROR.INVALID_PARAMETER
      CALL ExitError 'Error: Number of ''?'' chars in filemask too low for endnum.'
   END
   
   /* Delete old LogFile */
   IF FileExist( LogFile) THEN
      CALL SysFileDelete LogFile

   /* Process range of numbers */
   m = 0
   f = 0
   DO n = StartNum TO EndNum
      /* Build Filename */
      NumPart = RIGHT( n, NumPartLen, '0')
      Filename = OVERLAY( NumPart, FileMask, NumPartPos, NumPartLen)
      f = f + 1
      /*SAY RIGHT( f, NumPartLen)': 'Filename*/
     
      /* Search filename */
      IF \FileExist( Filename) THEN
      DO
         m = m + 1
         /* Write to LogFile */
         CALL WriteLog 'Missing: 'Filename
      END
   END
   
   /* Close LogFile if opened */
   IF STREAM( LogFile) = 'READY' THEN
      CALL STREAM LogFile, 'C', 'CLOSE'
   
   /* Report number of missing files */
   IF m = 0 THEN
      SAY 'All 'f' numbers exist.'   
   ELSE
      SAY m' file(s) of 'f' are missing. See 'LogFile'.'

END

EXIT( rc)

/* ======================================================================= */

/* ----------------------------------------------------------------------- */
FileExist: PROCEDURE EXPOSE (GlobalVars)
   rc = ERROR.NO_ERROR

   PARSE ARG Filename

   IF FileName = '' THEN
      RETURN( 0)
   ELSE
      RETURN( STREAM( Filename, 'C', 'QUERY EXISTS') <> '')

/* ----------------------------------------------------------------------- */
WriteLog: PROCEDURE EXPOSE (GlobalVars)
   PARSE ARG Message
   
   StreamState = STREAM( LogFile)
   IF WORDPOS( StreamState, 'UNKNOWN NOTREADY') > 0 THEN
   DO
      StreamState = STREAM( LogFile, 'C', 'OPEN')
      PARSE VAR StreamState StreamState':'
   END
   IF StreamState = 'READY' THEN
      CALL LINEOUT LogFile, Message
     
   RETURN( '')   

/* ----------------------------------------------------------------------- */
ShowHelp: PROCEDURE EXPOSE (GlobalVars)
   DO l = HelpStartLine TO HelpEndLine
      SAY SUBSTR( SOURCELINE( l), 3)
   END
   EXIT rc

/* ----------------------------------------------------------------------- */

ExitError: PROCEDURE EXPOSE (GlobalVars)
   PARSE ARG Message
   CALL ShowError Message
   EXIT rc   

/* ----------------------------------------------------------------------- */
/* Show error message in a message box and/or write to STDERR */
ShowError: PROCEDURE EXPOSE (GlobalVars)
   PARSE ARG Message
   CALL LINEOUT 'STDERR', Message

   RETURN( '')

/* ----------------------------------------------------------------------- */
Halt:
   CALL ShowError 'Interrupted by user.'
   EXIT( 99)

/* ----------------------------------------------------------------------- */
/* Give a standard REXX error message. */
/* This is for REXX error conditions only. */
/* System error codes and REXX error codes are different. */
RexxError:
   /* SIGL must be saved to not get overwritten later. */
   ErrorLine = SIGL

   /* As an extension to the standard REXX error messages,    */
   /* the error condition will be appended to the error text. */
   ConditionText = 'Condition: 'CONDITION( 'C')
   ConditionDescription = CONDITION( 'D')
   IF ConditionDescription <> '' THEN
      ConditionText = ConditionText', Reason: 'ConditionDescription

   ErrText = ''
   IF SYMBOL( 'rc') = 'VAR' THEN
   DO
      IF rc > 0 & rc < 100 THEN
         ErrText = ERRORTEXT( rc)
   END
   IF ErrText = '' THEN
      ErrText = ConditionText
   ELSE
      ErrText = ErrText', 'ConditionText

   /* Ensure that rc is set and that rc <> 0 is returned */
   IF SYMBOL( 'rc') = 'VAR' THEN
   DO
      IF \( rc > 0 & rc < 100) THEN
         rc = 999
   END
   ELSE
      rc = 999

   ErrorMessage = ''
   IF ErrorLine > 0 THEN
      ErrorMessage = RIGHT( ErrorLine, 6)' +++  'SOURCELINE( ErrorLine)
   IF ErrorMessage <> '' THEN
      ErrorMessage = ErrorMessage''CrLf
   ErrorMessage = ErrorMessage ||,
      'REX'RIGHT( rc, 4, 0)': Error 'rc' running 'ThisFile', line 'ErrorLine': 'ErrText
   CALL ShowError ErrorMessage

   EXIT( rc)


--- End code ---

Per E. Johannessen:
Thanks a lot Andreas, works like a dream.

Andreas Schnellbacher:
You're welcome.

That's almost the style from Christian. In 2002 and a few years later I had the chance to work on the same project with him and had learned a lot about programming styles and projects.

Navigation

[0] Message Index

[*] Previous page

Go to full version