I have spammed many duplicate posts from one initial and now after editing them the url structure for them is something like http://example.com/base-name-copy-20 where base-name is the slug of the duplicated initial post. Now, I could change the permalink for every one of them manually I know, but is there a way to create a slug for those duplicated posts anew ? I have edited them so they all have their own title now, but the permalink is already set. If I could reassign the permalinks the same way that wordpress automatically gives a slug for them initially would be nice.

Thanks in advance !

2 Answers 2


Editing the permalink manually would be the safest route. If you're comfortable using phpMyAdmin, you could create a MySQL query to update them all in one batch. Slightly more work than auto-assigning a slug, but it doesn't require a lot of coding to try to re-calculate the slugs.

update wp_posts SET post_name = 'new-slug' WHERE post_name = 'old-slug';

(You can copy and paste this onto multiple lines and update as many as you like in one operation.)

  • Thank you for pointing me in the right direction, I have searched further and perfected my script to solve my case :) Feb 21, 2017 at 8:41
  • Cool, perhaps you can edit the answer above to help others and mark as solved :)
    – WebElaine
    Feb 21, 2017 at 20:13
  • I already posted my full solution, but can't mark it yet due to the 24 hours limitation. Feb 22, 2017 at 13:51

After finding some interesting sources I ended up with this solution (added an extra function to take care of a few Dutch characters as well):

drop function if exists fn_remove_accents;
delimiter |
create function fn_remove_accents( textvalue varchar(20000) )
returns varchar(20000)

set @textvalue = textvalue;

set @withaccents = 'ŠšŽžÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝŸÞàáâãäåæçèéêëìíîïñòóôõöøùúûüýÿþƒ';
set @withoutaccents = 'SsZzAAAAAAACEEEEIIIINOOOOOOUUUUYYBaaaaaaaceeeeiiiinoooooouuuuyybf';
set @count = length(@withaccents);

while @count > 0 do
    set @textvalue = replace(@textvalue, substring(@withaccents, @count, 1), substring(@withoutaccents, @count, 1));
    set @count = @count - 1;
end while;

set @special = '!@#$%¨&*()_+=§¹²³£¢¬"`´{[^~}]<,>.:;?/°ºª+*|\\''';
set @count = length(@special);
while @count > 0 do
    set @textvalue = replace(@textvalue, substring(@special, @count, 1), '');
    set @count = @count - 1;
end while;

return @textvalue;


CREATE DEFINER=`root`@`localhost` # I have no idea what this does
FUNCTION `slugify`(dirty_string varchar(200))
RETURNS varchar(200) CHARSET latin1
    DECLARE x, y , z Int;
    Declare temp_string, allowed_chars, new_string VarChar(200);
    Declare is_allowed Bool;
    Declare c, check_char VarChar(1);

    set allowed_chars = "abcdefghijklmnopqrstuvwxyz0123456789-";
    set temp_string = fn_remove_accents(LOWER(dirty_string));
    Select temp_string Regexp('&') Into x;
    If x = 1 Then
        Set temp_string = replace(temp_string, '&', ' and ');
    End If;

    Select temp_string Regexp('[^a-z0-9]+') into x;
    If x = 1 then
        set z = 1;
        While z <= Char_length(temp_string) Do
            Set c = Substring(temp_string, z, 1);
            Set is_allowed = False;
            Set y = 1;
            Inner_Check: While y <= Char_length(allowed_chars) Do
                If (strCmp(ascii(Substring(allowed_chars,y,1)), Ascii(c)) = 0) Then
                    Set is_allowed = True;
                    Leave Inner_Check;
                End If;
                Set y = y + 1;
            End While;
            If is_allowed = False Then
                Set temp_string = Replace(temp_string, c, '-');
            End If;

            set z = z + 1;
        End While;
    End If;

    Select temp_string Regexp("^-|-$|'") into x;
    If x = 1 Then
        Set temp_string = Replace(temp_string, "'", '');
        Set z = Char_length(temp_string);
        Set y = Char_length(temp_string);
        Dash_check: While z > 1 Do
            If Strcmp(SubString(temp_string, -1, 1), '-') = 0 Then
                Set temp_string = Substring(temp_string,1, y-1);
                Set y = y - 1;
                Leave Dash_check;
            End If;
            Set z = z - 1;
        End While;
    End If;

        Select temp_string Regexp("--") into x;
        If x = 1 Then
            Set temp_string = Replace(temp_string, "--", "-");
        End If;
    Until x <> 1 End Repeat;

    Return temp_string;

UPDATE wp_posts SET post_name = slugify(post_title) WHERE post_name LIKE '%copy%' AND post_type = 'MY_POST_TYPE';

Explaining the query: The first two functions are directly taken from sources 1 and 2, with a small edit to handle uppercase characters too.

Finally the update query will match on those duplicated posts that have the word copy in their slug, but depending on your case, you probably want to make this rule more strict. I want to run this query on my custom post type, so I added an extra check for the post type on the query, not a big deal.

The matched posts will be assigned a newly generated slug based on their title (post_title), alternatively you can specify a different source for the slug generation.


[1] Replace non-latin characters selectively

[2] Regenerate a slug from a free-text name

[3] WebElaine's answer (on this page)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.