Bulk rename files on media device matched with regex on Windows

后端 未结 1 412
忘了有多久
忘了有多久 2020-12-22 10:23

I feel like I could do this fairly easily on a linux machine with bash, but I don\'t have enough experience with Batch to do it.

Basically, a lot of the music files

相关标签:
1条回答
  • 2020-12-22 10:47

    I've been meaning to do this for a while anyway.

    There's a handy Perl rename script written years ago by Larry Wall that I often use to rename files via regexp. But since I rarely have need for Perl in Windows, and installing Perl just for this one script seems like a waste, I always thought it'd be a good idea to rewrite prename using native Windows scripting languages.

    Hopefully if there are any bugs, they won't be too debilitating. I didn't test the script a whole lot, but it seems to work fine for basic usage where the files you're renaming live in your current working directory. Bonus: backreferences work in your replacement text. Wooo.

    Example usage

    prename.bat -v "s/searchRXP/replacement/flags" filemask
    

    See prename.bat -h in a console window for full usage help.

    prename.bat

    <!-- : prename.bat -- http://stackoverflow.com/a/38191137/1683264
    @echo off & setlocal
    
    rem // ensure flags and other vars begin undefined
    for %%I in (v n f h show filemask search replace flags) do set %%I=
    
    rem // organize arguments
    for /f "delims=" %%I in ('cscript //nologo //job:args "%~f0?.wsf" %*') do set "%%~I"
    if defined h goto usage
    if defined invalid (
        echo Unrecognized option: %invalid%
        goto usage
    )
    if not defined filemask goto usage
    if not defined search goto usage
    if defined v set "show=1"
    if defined n set "show=1"
    
    rem // expand wildcards
    for %%I in (%filemask%) do (
        for /f "delims=" %%# in ('cscript //nologo //job:newname "%~f0?.wsf" "%%~I"') do (
            if defined show echo %%~I -^> %%~#
            if not defined n if not "%%~fI"=="%%~f#" (
                >NUL (
                    if defined f (move /y "%%~I" "%%~#") else ren "%%~I" "%%~nx#"
                )
            )
        )
    )
    
    goto :EOF
    
    :usage
    echo Usage: %~nx0 [-v] [-n] [-f] perlexpr [filelist]
    echo    -v shows verbose output
    echo    -n performs a simulation only
    echo    -f forces overwriting existing files
    echo    perlexpr is a Perl-compatible regular expression
    echo    filelist can contain wildcards
    echo;
    echo Example:
    echo    %~nx0 -n "s/([^\.]+)$/\1.cmd/i" *.bat
    echo This would simulate renaming every .bat file extension to .bat.cmd
    goto :EOF
    
    : end batch begin JScript hybrid code -->
    <package>
        <job id="args">
            <script language="JScript">
                var args = {
                        v: 0,
                        n: 0,
                        f: 0,
                        h: 0,
                        search: '',
                        replace: '',
                        flags: '',
                        filemask: ''
                    };
    
                for (var i=0; i<WSH.Arguments.length; i++) {
                    if (/^[\/-](.)/.test(WSH.Arguments(i))) {
                        if (typeof args[RegExp.$1] === 'undefined')
                            args.invalid = WSH.Arguments(i);
                        args[RegExp.$1] = 1;
                    }
                    else if (/^s(\W)(.+)\1(.*)\1(.*)/.test(WSH.Arguments(i))) {
                        args.search = RegExp.$2;
                        args.replace = RegExp.$3;
                        args.flags = RegExp.$4;
                    }
                    else args.filemask += ';' + '"' + WSH.Arguments(i) + '"';
                }
                for (var i in args) if (args[i]) WSH.Echo(i + '=' + args[i]);
            </script>
        </job>
        <job id="newname">
            <script language="JScript">
                var env = WSH.CreateObject('WScript.Shell').Environment('Process'),
                    search = env('search'),
                    repl = env('replace'),
                    flags = env('flags');
    
                WSH.Echo(WSH.Arguments(0).replace(
                    new RegExp(search, flags),
                    function(full, $1, $2, $3, $4, $5, $6, $7, $8, $9) {
                        var backref = [full, $1, $2, $3, $4, $5, $6, $7, $8, $9];
                        return repl.replace(
                            /[\\$](\d)/g,
                            function(full, $1) { return backref[$1]; }
                        );
                    }
                ));
            </script>
        </job>
    </package>
    
    0 讨论(0)
提交回复
热议问题