View Raw SPL
/****************************************************************************
*                                                                           *
*   FILESTRREP.SPL Copyright 2010-2026 (C) DSP Development Corporation      *
*                                                                           *
*   Author:        Randy Race                                               *
*                                                                           *
*   Synopsis:      Replaces target strings in a list of files               *
*                                                                           *
*   Revisions:     11 Apr 2010     RRR     Creation                         *
*                  19 Jun 2010     RRR     fputs no escape translation      *
*                   5 Jun 2026     RRR     wildcard & regex support         *
*                                                                           *
****************************************************************************/

#if @HELP_FILESTRREP

    FILESTRREP

    Purpose: Replaces a pattern string with a new pattern for each input file

    Syntax:  FILESTRREP("filespec", "patstr", "repstr", recurse, caseflag,
                         maxmatches, wildcard)

                 filespec - A string, the list of files to process. Filespec
                            can include wildcard characters such as * and ?.
                          
                   patstr - A string, the pattern to search for.

                   repstr - A string, the replacement pattern.

                  recurse - Optional. An integer, recurse into sub-directories
                            if found.

                             0: do not recurse (default)
                             1: recurse

                 caseflag - Optional. An integer, the case sensitivity flag. 
 
                             0: case not significant
                             1: case significant (default)

               maxmatches - Optional. An integer, the maximum number of matches to
                            process. Defaults to -1, process all matches.

                 wildcard - Optional. An integer, process * (any sequence)
                            and ? (single character) as wildcard characters
                            or use regular expressions (regex) in "patstr".
                           
                             0: no wildcards and no regular expressions (default)
                             1: support * and ? wildcards
                             2: support regular expressions (regex)
 
    Returns: An integer, the number of files where the replacement occured.

    Example:
             filestrrep("\temp\*.txt", "January", "April")

             Returns the count of the number of files in the "\temp" folder
             with extension ".txt" where the text "January" was replaced
             with the text "April".

    Remarks:
             The pattern and replacement strings are case sensitive.

             If the pattern string is not found in a file, the file remains
             unchanged.

             When WILDCARD is set to 1, use * in "patstr" to match any character
             sequence and ? to matcha single character. To search for a literal
             * or ? character instead of treating them as wildcards, escape them by
             prefixing a backslash: \* or \?.

             When WILDCARD is set to 2, the search pattern "patstr", is interpreted
             as a regular expression. Regular expressions (regex) provide far more
             flexibility than simple wildcards. A regular expression can indicate
             character classes(match a character from a set), quantifiers
             (how many times a patternrepeats), anchors (position in the string)
             and logical operators.

             When wildcard is 2, the replacement string "repstr", supports
             backreferences and substitution tokens.

             See STRREP for a discussion of regular expressions.

    See Also:
             STRREP
#endif


/* replaces a string in all files in a directory */
filestrrep(filespec, srcstr, targstr, recurse = 0, caseflag = 1, maxmatches = -1, wildcard = 0, verbose = 0)
{
        local dirlist, filelist, file, filedir, temp, i, j, cnt = 0, num;

        if (argc < 3)
        {
                error(sprintf("%s - file specification, search string and target string required", __FUNC__));
        }

        /* check inputs */
        if (strlen(srcstr) == 0 || strlen(filespec) == 0)
        {
                return(0);
        }

        /* get directory */
        (dir, temp) = dirpath(filespec, 1);

        /* get newline delimited filelist */
        (filelist, num) = filerep_filelist(filespec, recurse);

        i = 1;

        while (1)
        {
                /* get file name from list */
                file = strget(i, filelist, strescape("\n"));
                
                if (strlen(file) > 0)
                {
                        /* get directory */
                        (filedir, temp) = dirpath(file, 0);
                        
                        if (strlen(filedir) <= 0)
                        {
                                /* fullname */
                                file = dir + file;
                        }

                        /* replace string */
                        cnt += filerep_replace(srcstr, targstr, file, caseflag, maxmatches, wildcard);
                        i++;

                        if (verbose)
                        {
                                echo(sprintf("Files %ld of %ld, Replaced %ld", i, num, cnt));
                        }
                }
                else
                {
                        break;
                }
        }
        
        return(cnt);
}


/* returns a newline delimited list of files */
filerep_filelist(spec, recurse)
{
        local tempfile, cmd, options, s = "";

        if (argc < 2)
        {
                if (argc < 1) spec = "*.*";
                
                recurse = 0;
        }

        /* flag to recurse into sub-directories */
        options = recurse ? "/S" : "";

        /* build temporary file */
        tempfile = getmiscpath(1, 1) + "templist.txt";

        /* directory listing command */
        cmd = sprintf('dir "%s" /b %s > "%s"', spec, options, tempfile);

        /* run listing */
        run(cmd, -1);

        /* check tempfile existence */
        if (fstat(tempfile) > 0)
        {
                /* return listing as a string */
                s = strfile(tempfile, 0, 1, 0, 0);
                delfile(tempfile);
        }

        /* number of files */
        num = strmatch(strescape("\n"), s);
        num = length(num);

        return(s, num);
}


/* replace srcstr with targstr in a file */
filerep_replace(srcstr, targstr, fname, caseflag, maxmatches, wildcard)
{
        local instr, outstr, status = 0;

        /* convert to string */
        instr = strchars(readb(fname, ubyte));

        if (strlen(instr) > 0)
        {
                /* case sensitive replace */
                outstr = strrep(instr, srcstr, targstr, caseflag, maxmatches, wildcard);

                /* check if any changes were made */
                if (outstr != instr)
                {
                        /* save changes to original file */
                        writeb(fname, ubyte, 1, charstrs(outstr));

                        status = 1;
                }
        }
        
        return(status);
}


filerep_replace_error()
{
        return(0);
}