No internet connection
  1. Home
  2. Script Sharing

Replace accented and special characters on files and folders' names

By samuel henriques @samuel_henriques
    2021-01-24 23:24:37.018Z

    Hello everyone,
    Here's a little script to replace all accents and weird characters from the names of files and folders straight in the finder.
    And just in case I made an undo.
    It works by taking each selected file/folder and "fixing" one at a time, so the undo will work if the same order of the original selection of the files/folders. If the order is different it will rename thinking the previous order still exists and it will not end well.
    I don't take credit for the function cleanUpSpecialChars I took a lot of inspiration from the "internet".
    Let me know if there is a better way of going about this.

    To replace:

    
    function cleanUpSpecialChars(str) {
        return str
    
            .replace(/[AⒶAÀÁÂẦẤẪẨÃĀĂẰẮẴẲȦǠÄǞẢÅǺǍȀȂẠẬẶḀĄ]/g, 'A')
            .replace(/[Ꜳ]/g, 'AA')
            .replace(/[ÆǼǢ]/g, 'AE')
            .replace(/[Ꜵ]/g, 'AO')
            .replace(/[Ꜷ]/g, 'AU')
            .replace(/[ꜸꜺ]/g, 'AV')
            .replace(/[Ꜽ]/g, 'AY')
            .replace(/[BⒷBḂḄḆɃƂƁ]/g, 'B')
            .replace(/[CⒸCĆĈĊČÇḈƇȻꜾ]/g, 'C')
            .replace(/[DⒹDḊĎḌḐḒḎĐƋƊƉꝹ]/g, 'D')
            .replace(/[DZDŽ]/g, 'DZ')
            .replace(/[DzDž]/g, 'Dz')
            .replace(/[EⒺEÈÉÊỀẾỄỂẼĒḔḖĔĖËẺĚȄȆẸỆȨḜĘḘḚƐƎ]/g, 'E')
            .replace(/[FⒻFḞƑꝻ]/g, 'F')
            .replace(/[GⒼGǴĜḠĞĠǦĢǤƓꞠꝽꝾ]/g, 'G')
            .replace(/[HⒽHĤḢḦȞḤḨḪĦⱧⱵꞍ]/g, 'H')
            .replace(/[IⒾIÌÍÎĨĪĬİÏḮỈǏȈȊỊĮḬƗ]/g, 'I')
            .replace(/[JⒿJĴɈ]/g, 'J')
            .replace(/[KⓀKḰǨḲĶḴƘⱩꝀꝂꝄꞢ]/g, 'K')
            .replace(/[LⓁLĿĹĽḶḸĻḼḺŁȽⱢⱠꝈꝆꞀ]/g, 'L')
            .replace(/[LJ]/g, 'LJ')
            .replace(/[Lj]/g, 'Lj')
            .replace(/[MⓂMḾṀṂⱮƜ]/g, 'M')
            .replace(/[NⓃNǸŃÑṄŇṆŅṊṈȠƝꞐꞤ]/g, 'N')
            .replace(/[NJ]/g, 'NJ')
            .replace(/[Nj]/g, 'Nj')
            .replace(/[OⓄOÒÓÔỒỐỖỔÕṌȬṎŌṐṒŎȮȰÖȪỎŐǑȌȎƠỜỚỠỞỢỌỘǪǬØǾƆƟꝊꝌ]/g, 'O')
            .replace(/[Ƣ]/g, 'OI')
            .replace(/[Ꝏ]/g, 'OO')
            .replace(/[Ȣ]/g, 'OU')
            .replace(/[PⓅPṔṖƤⱣꝐꝒꝔ]/g, 'P')
            .replace(/[QⓆQꝖꝘɊ]/g, 'Q')
            .replace(/[RⓇRŔṘŘȐȒṚṜŖṞɌⱤꝚꞦꞂ]/g, 'R')
            .replace(/[SⓈSẞŚṤŜṠŠṦṢṨȘŞⱾꞨꞄ]/g, 'S')
            .replace(/[TⓉTṪŤṬȚŢṰṮŦƬƮȾꞆ]/g, 'T')
            .replace(/[Ꜩ]/g, 'TZ')
            .replace(/[UⓊUÙÚÛŨṸŪṺŬÜǛǗǕǙỦŮŰǓȔȖƯỪỨỮỬỰỤṲŲṶṴɄ]/g, 'U')
            .replace(/[VⓋVṼṾƲꝞɅ]/g, 'V')
            .replace(/[Ꝡ]/g, 'VY')
            .replace(/[WⓌWẀẂŴẆẄẈⱲ]/g, 'W')
            .replace(/[XⓍXẊẌ]/g, 'X')
            .replace(/[YⓎYỲÝŶỸȲẎŸỶỴƳɎỾ]/g, 'Y')
            .replace(/[ZⓏZŹẐŻŽẒẔƵȤⱿⱫꝢ]/g, 'Z')
            .replace(/[aⓐaẚàáâầấẫẩãāăằắẵẳȧǡäǟảåǻǎȁȃạậặḁąⱥɐ]/g, 'a')
            .replace(/[ꜳ]/g, 'aa')
            .replace(/[æǽǣ]/g, 'ae')
            .replace(/[ꜵ]/g, 'ao')
            .replace(/[ꜷ]/g, 'au')
            .replace(/[ꜹꜻ]/g, 'av')
            .replace(/[ꜽ]/g, 'ay')
            .replace(/[bⓑbḃḅḇƀƃɓ]/g, 'b')
            .replace(/[cⓒcćĉċčçḉƈȼꜿↄ]/g, 'c')
            .replace(/[dⓓdḋďḍḑḓḏđƌɖɗꝺ]/g, 'd')
            .replace(/[dzdž]/g, 'dz')
            .replace(/[eⓔeèéêềếễểẽēḕḗĕėëẻěȅȇẹệȩḝęḙḛɇɛǝ]/g, 'e')
            .replace(/[fⓕfḟƒꝼ]/g, 'f')
            .replace(/[gⓖgǵĝḡğġǧģǥɠꞡᵹꝿ]/g, 'g')
            .replace(/[hⓗhĥḣḧȟḥḩḫẖħⱨⱶɥ]/g, 'h')
            .replace(/[ƕ]/g, 'hv')
            .replace(/[iⓘiìíîĩīĭïḯỉǐȉȋịįḭɨı]/g, 'i')
            .replace(/[jⓙjĵǰɉ]/g, 'j')
            .replace(/[kⓚkḱǩḳķḵƙⱪꝁꝃꝅꞣ]/g, 'k')
            .replace(/[lⓛlŀĺľḷḹļḽḻſłƚɫⱡꝉꞁꝇ]/g, 'l')
            .replace(/[lj]/g, 'lj')
            .replace(/[mⓜmḿṁṃɱɯ]/g, 'm')
            .replace(/[nⓝnǹńñṅňṇņṋṉƞɲʼnꞑꞥ]/g, 'n')
            .replace(/[nj]/g, 'nj')
            .replace(/[oⓞoòóôồốỗổõṍȭṏōṑṓŏȯȱöȫỏőǒȍȏơờớỡởợọộǫǭøǿɔꝋꝍɵ]/g, 'o')
            .replace(/[ƣ]/g, 'oi')
            .replace(/[ȣ]/g, 'ou')
            .replace(/[ꝏ]/g, 'oo')
            .replace(/[pⓟpṕṗƥᵽꝑꝓꝕ]/g, 'p')
            .replace(/[qⓠqɋꝗꝙ]/g, 'q')
            .replace(/[rⓡrŕṙřȑȓṛṝŗṟɍɽꝛꞧꞃ]/g, 'r')
            .replace(/[sⓢsßśṥŝṡšṧṣṩșşȿꞩꞅẛ]/g, 's')
            .replace(/[tⓣtṫẗťṭțţṱṯŧƭʈⱦꞇ]/g, 't')
            .replace(/[ꜩ]/g, 'tz')
            .replace(/[uⓤuùúûũṹūṻŭüǜǘǖǚủůűǔȕȗưừứữửựụṳųṷṵʉ]/g, 'u')
            .replace(/[vⓥvṽṿʋꝟʌ]/g, 'v')
            .replace(/[ꝡ]/g, 'vy')
            .replace(/[wⓦwẁẃŵẇẅẘẉⱳ]/g, 'w')
            .replace(/[xⓧxẋẍ]/g, 'x')
            .replace(/[yⓨyỳýŷỹȳẏÿỷẙỵƴɏỿ]/g, 'y')
            .replace(/[zⓩzźẑżžẓẕƶȥɀⱬꝣ]/g, 'z')
            .replace(/[^a-z0-9-._/   ]/gi, ''); // final clean up
    
    
    }
    
    
    function renameFolder(oldFileNamePath) {
    
        const oldFileName = oldFileNamePath.slice(0, -1).split("/").slice(-1).join("/")
        const newFileName = cleanUpSpecialChars(oldFileName)
        const newFileNamePath = oldFileNamePath.slice(0, -1).split("/").slice(0, -1).join("/") + "/" + newFileName + "/"
    
        sf.file.directoryMove({
            sourcePath: oldFileNamePath,
            destinationPath: newFileNamePath,
        });
    }
    
    
    function renameFile(oldFileNamePath) {
    
        const oldFileName = oldFileNamePath.split("/").slice(-1).join("/")
        const newFileName = cleanUpSpecialChars(oldFileName)
        const newFileNamePath = oldFileNamePath.split("/").slice(0, -1).join("/") + "/" + newFileName
    
        sf.file.move({
            sourcePath: oldFileNamePath,
            destinationPath: newFileNamePath,
        });
    }
    
    
    
    function main() {
    
        sf.ui.finder.appActivate()
    
        const selectedFinder = sf.ui.finder.selectedPaths;
    
        globalState.rememberSelectedFinder = selectedFinder
    
        for (let i = 0; i < selectedFinder.length; i++) {
    
            const oldFileNamePath = selectedFinder[i]
    
            if (oldFileNamePath.charAt(oldFileNamePath.length - 1) === "/") {
                renameFolder(oldFileNamePath)
    
            } else {
                renameFile(oldFileNamePath)
            }
        }
    }
    
    main()
    

    To undo:

    function rememberNames() {
    
        sf.ui.finder.appActivate()
    
        const selectedFinder = sf.ui.finder.selectedPaths;
    
        for (let i = 0; i < selectedFinder.length; i++) {
    
            const oldFileNamePath = selectedFinder[i]
            const oldFileName = oldFileNamePath.split("/").slice(-1).join("/")
    
            const newFileNamePath = globalState.rememberSelectedFinder[i]
    
    
            if (oldFileNamePath.charAt(oldFileNamePath.length - 1) === "/") {
                sf.file.directoryMove({
                    sourcePath: oldFileNamePath,
                    destinationPath: newFileNamePath,
                });
    
            } else {
                sf.file.move({
                    sourcePath: oldFileNamePath,
                    destinationPath: newFileNamePath,
                });
            }
        }
    }
    
    
    rememberNames()
    
    • 2 replies
    1. This is great stuff, Samuel! Thanks for sharing!

      1. Thanks for sharing! I wondered how you did this - great code :)