# Replace a string in all posts

**URL:** https://meta.discourse.org/t/replace-a-string-in-all-posts/48729
**Category:** Self-Hosting
**Tags:** how-to
**Created:** [August 17, 2016, 10:23am UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729 "2016-08-17T10:23:49Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Discourse](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/discourse/32/148734_2.png) [@Discourse](https://meta.discourse.org/u/Discourse)
#### Post date: [August 17, 2016, 10:23am UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/1 "2016-08-17T10:23:49Z")

</div>

> 🔖 This guide explains how to replace a string in all posts within a Discourse instance.
> 
> 🙋 Required user level: System Administrator
> 
> ⚠ Console Access Required

Want to replace a string in all the posts on a site? Let’s get started!

> ⚠ **WARNING:** We _strongly_ recommend you take a full backup before proceeding, and make _sure_ your string replacement is specific enough to affect _only_ the places you want it to. If this string replacement goes wrong, every post on your site will look broken!

## Access your site

Start by accessing your Discourse instance via SSH and entering the Docker container:

```bash
cd /var/discourse
./launcher enter app

```

## Performing string replacements

### Basic case-sensitive replacement

To replace a string, use the following command. Replace `find` with the string to locate and `replace` with the desired substitution:

```bash
rake 'posts:remap[find,replace]'

```

Example results:

> find —\> replace  
> Find —\> Find  
> FIND —\> FIND  
> finders keepers —\> replaceers keepers  
> finding —\> replaceing

This method can be useful for tasks such as replacing emojis:

```bash
rake 'posts:remap[:slightly_smiling:,:slight_smile:]'

```

The above command will replace all occurrences of `:slightly_smiling:` with `:slight_smile:`.

### Case-insensitive replacement

For replacements that ignore case sensitivity use:

```bash
rake 'posts:remap[find,replace,string,true]'

```

Example results:

> find —\> replace  
> Find —\> replace  
> FIND —\> replace  
> finders keepers —\> replaceers keepers  
> finding —\> replaceing

### Regex replacement

For advanced replacements with regex, format the command accordingly:

```bash
rake 'posts:remap[(?<!\\w)(?=\\w)find(?<=\\w)(?!\\w),replace,regex]'

```

Example results:

> replace —\> replace  
> Find —\> Find  
> FIND —\> FIND  
> finders keepers —\> finders keepers  
> finding —\> finding

## Deleting words or strings

To completely remove a word or string, apply these commands:

### Basic case-sensitive deletion

```bash
rake 'posts:delete_word[word-to-delete]'

```

### Case-insensitive deletion

```bash
rake 'posts:delete_word[word-to-delete,string,true]'

```

### Regex deletion

```bash
rake 'posts:delete_word[\\[color=#[0-9a-fA-F]{3,6}\\],regex]'

```

> Last edited by @SaraDev 2024-11-14T00:39:05Z
> 
> > **Check document**
> >
> > Perform check on document:

---

<div class="post-metadata">

### Author: ![nathank](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nathank/32/290039_2.png) [@nathank](https://meta.discourse.org/u/nathank)
#### Post date: [May 12, 2022, 6:17am UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/147 "2022-05-12T06:17:35Z")

</div>

How would I do this for just the topics in a single category?

My use case is an imported RSS feed which annoyingly displays a `?` instead of a `'`. And as the feed is a news feed with lots of quotations, this is a problem!

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [May 12, 2022, 5:19pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/148 "2022-05-12T17:19:10Z")

</div>

> [@nathankershaw](#):
>
> How would I do this for just the topics in a single category?

You’d do it from rails, and it’ll be hard because posts don’t belong to categories, topics do. Sounds like you need a plugin if this is a continual issue. You could be clever with a join or just loop like

```plaintext
Topics.where(category_id: 123).each do |t|
  posts.where(topic_id: t, post_number: 1).each do |p|
    if p.raw.match("?")
        p.raw.gsub!("?","'")
        p.save
    end
  end
end

```

If it’s not only in `post_number: `, don’t include that.

If it’s not a huge number of posts, then this is probably good enough, if it works at all.

---

<div class="post-metadata">

### Author: ![nathank](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nathank/32/290039_2.png) [@nathank](https://meta.discourse.org/u/nathank)
#### Post date: [May 12, 2022, 10:02pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/149 "2022-05-12T22:02:07Z")

</div>

Thanks Jay! That would do the trick nicely.

> [@pfaffman](#):
>
> Sounds like you need a plugin if this is a continual issue.

I do need to troubleshoot it properly and see if there is an upstream fix. Or I might need to bolt something onto the [RSS Polling Plugin](https://meta.discourse.org/t/configure-the-discourse-rss-polling-plugin/156387) which is a bit of a tricky beast!

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [May 12, 2022, 10:09pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/150 "2022-05-12T22:09:50Z")

</div>

> [@nathankershaw](#):
>
> My use case is an imported RSS feed which annoyingly displays a `?` instead of a `'` .

Just a guess, but are you seeing any other issues with posts created from the RSS feed? Are the `?` characters present when you view the feed’s source? I’m wondering if what you are running into is an encoding issue.

---

<div class="post-metadata">

### Author: ![nathank](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nathank/32/290039_2.png) [@nathank](https://meta.discourse.org/u/nathank)
#### Post date: [May 12, 2022, 10:15pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/151 "2022-05-12T22:15:17Z")

</div>

> [@simon](#):
>
> Are the `?` characters present when you view the feed’s source?

Yeah, I’m just looking at this now. The `?` are in there every time there is an unusual character, so it is a problem at the RSS source end. It turns out that `'` is just the most common one, but it is also happening for `ā`, `"`, and one or two others.

Unfortunately the software company involved isn’t quite as responsive as the Discourse team 😘! Wish me luck.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [May 12, 2022, 10:52pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/152 "2022-05-12T22:52:16Z")

</div>

> [@simon](#):
>
> I’m wondering if what you are running into is an encoding issue.

That’s what I was suspecting too. It might be as simple as better detecting the right encoding.

---

<div class="post-metadata">

### Author: ![Chandra](https://avatars.discourse-cdn.com/v4/letter/c/57b2e6/32.png) [@Chandra](https://meta.discourse.org/u/Chandra)
#### Post date: [October 14, 2022, 7:50pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/153 "2022-10-14T19:50:47Z")

</div>

Any guidance to replace as below please?

[member=12345] → @

---

<div class="post-metadata">

### Author: ![Brandon007](https://avatars.discourse-cdn.com/v4/letter/b/b4bc9f/32.png) [@Brandon007](https://meta.discourse.org/u/Brandon007)
#### Post date: [November 19, 2022, 2:57pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/154 "2022-11-19T14:57:49Z")

</div>

> [@techAPJ](#):
>
> `rake posts:remap["find","replace","string",true]`

I used this example which works for replacing a URL. However, it’s not working for phrases.

Example:

`rake posts:remap["I Don't Want This Phrase","But I Do Want This One","string",true]`

I keep getting this error:

`ERROR: Expecting rake posts:remap['find','replace',type] where type is string or regex`

I tried it with the single quotes as shown in the error message as well, but no dice. I even tried by placing dashes between the words like in the delete word example. That gave me the same error.

Any advice?

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [November 19, 2022, 3:38pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/155 "2022-11-19T15:38:59Z")

</div>

I’m afraid that if you need to do something with quotes it’s best to do it in rails. With the rake task, you’ve got to deal with both `bash` and rails to escape. You might be able to use a bunch of backslashes (that also need to be escaped), but probably not.

Have a look at the rails example that I have above and see if that makes sense. I’ll to add something to the OP next time I have a laptop.

---

<div class="post-metadata">

### Author: ![Brandon007](https://avatars.discourse-cdn.com/v4/letter/b/b4bc9f/32.png) [@Brandon007](https://meta.discourse.org/u/Brandon007)
#### Post date: [November 19, 2022, 4:21pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/156 "2022-11-19T16:21:57Z")

</div>

Thanks for the response. That looks over my head, I can sure learn though.

It sounds like the quotes in the text string is what caused my issue…

My purpose, I find myself changing titles and urls to my blog, so I like to go back to the forum and update those links, the titles and urls as well. I can see this being a semi-regular task when I’m working on SEO. Any more details would be fantastic.

---

<div class="post-metadata">

### Author: ![rahim123](https://avatars.discourse-cdn.com/v4/letter/r/df705f/32.png) [@rahim123](https://meta.discourse.org/u/rahim123)
#### Post date: [January 6, 2023, 1:57pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/157 "2023-01-06T13:57:16Z")

</div>

There must be something I’m not understanding here. I’m trying to replace occurrences of `:THUMBS-UP:` with `:+1:` across almost 3M posts (including PMs). I ran:  
`rake posts:remap[":THUMBS-UP:",":+1:"]`  
And after about 50 minutes of `.................` it returned `40000 posts remapped!` This seems like a suspiciously even number. I did find some occurrences that were replaced with `:+1:` in both recent posts and posts from many years ago, but there are also a ton of `:THUMBS-UP:` even in the same topic threads that also have some successful `:+1:` replacements.

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [January 6, 2023, 4:07pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/158 "2023-01-06T16:07:24Z")

</div>

That sure seems a bit weird. Did you try to remap again?  
You can also easily return the number of posts that still contains `:THUMBS-UP:` using data-explorer if this info can be of some use.

---

<div class="post-metadata">

### Author: ![rahim123](https://avatars.discourse-cdn.com/v4/letter/r/df705f/32.png) [@rahim123](https://meta.discourse.org/u/rahim123)
#### Post date: [January 6, 2023, 5:33pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/159 "2023-01-06T17:33:59Z")

</div>

Yeah, it’s weird. I did try running the same command ~~two~~ three more times, and each time it remapped 333 more posts… ❓

In the log it’s showing a bunch of supposed replacements, except that when I reload the page and inspect the actual post it remains unchanged:

 ![Screenshot from 2023-01-06 12-42-28](https://global.discourse-cdn.com/meta/original/4X/f/9/e/f9eab972fb8a51a378f2ae1684cba077e3c359df.png)

This seemed to me like a caching issue, so I did a `redis-cli flushall` and hard-reloaded Discourse, but still no change in the posts that were reported as edited in the log.

And also in the error log a bunch of messages like this:  
 ![Screenshot from 2023-01-06 12-47-36](https://global.discourse-cdn.com/meta/optimized/4X/6/b/b/6bbf5d8ca518769cdc160daf1830ada0f4dba01e_2_690x23.png)

---

<div class="post-metadata">

### Author: ![supermathie](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/supermathie/32/507518_2.png) [@supermathie](https://meta.discourse.org/u/supermathie)
#### Post date: [January 6, 2023, 6:06pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/160 "2023-01-06T18:06:30Z")

</div>

> [@Brandon007](#):
>
> `rake posts:remap["I Don't Want This Phrase","But I Do Want This One","string",true]`

This should be fine… but one of the problems is that it _looks_ like you can quote other things such as commas, but you can’t since the quotes are consumed by the shell, not by the rake parser.

e.g.:

```plaintext
→ rake posts:remap["a,b","a+b"]
ERROR: Expecting rake posts:remap['find','replace',type] where type is string or regex

```

And the brackets should be quoted since they’re shell metachars themselves. You won’t even be able to run the command with a file called `posts:remapa` in the directory (unlikely as this may be) or with `failglob` set.

> [@techAPJ](#):
>
> `rake posts:remap[":slightly_smiling:",":slight_smile:"]`

I think we should change these commands - they’re misleading in the sense that they _look_ like you’re quoting the strings being replaced, but we really aren’t. The quotes are consumed by the shell; rails never sees them. No reason to even have the quotes, and if rails does see them they’ll be part of the string:

```plaintext
→ rake 'posts:remap["find","replace"]'
Are you sure you want to replace all string occurrences of '"find"' with '"replace"'? (Y/n)

```

Some more examples including how to deal with things like commas are:

```plaintext
rake 'posts:remap[find,replace,string,true]'
rake $'posts:remap[string with a quote\',string without a quote]'
rake 'posts:remap[a\, b,a+b]'

```

though, quirkily, this works:

```plaintext
→ rake 'posts:remap[string with a bracket] either quoted\] or not,string without a bracket]'
Are you sure you want to replace all string occurrences of 'string with a bracket] either quoted] or not' with 'string without a bracket'? (Y/n)

```

---

<div class="post-metadata">

### Author: ![supermathie](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/supermathie/32/507518_2.png) [@supermathie](https://meta.discourse.org/u/supermathie)
#### Post date: [January 6, 2023, 7:06pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/161 "2023-01-06T19:06:28Z")

</div>

> [@rahim123](#):
>
> when I reload the page and inspect the actual post it remains unchanged

Is it possible the raw is changed, but the (new) post is not yet baked?

---

<div class="post-metadata">

### Author: ![rahim123](https://avatars.discourse-cdn.com/v4/letter/r/df705f/32.png) [@rahim123](https://meta.discourse.org/u/rahim123)
#### Post date: [January 6, 2023, 7:08pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/162 "2023-01-06T19:08:24Z")

</div>

I thought about that too, but no, I hit the edit button on those posts and the raw is unchanged. And on the successful replacements the new emoji appears without a rebake.

---

<div class="post-metadata">

### Author: ![MiG](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mig/32/119486_2.png) [@MiG](https://meta.discourse.org/u/MiG)
#### Post date: [January 17, 2023, 3:36am UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/163 "2023-01-17T03:36:41Z")

</div>

So I’m trying to replace 600+ instances of an imported YouTube links, but it seems to only work when it’s on a line by itself.

So I need to insert a newline before the YouTube link itself. Thankfully, I have a “replaceme” type of string that can be replaced with the newline.

Is the appropriate way to do a Ruby newline? Or a Markdown newline?

Would something like this work?

```plaintext
rake posts:remap["replaceme","\n",string,true]

```

Or do I need to escape the \n a few times?

```plaintext
rake posts:remap["replaceme","\\\n",string,true]

```

Or should I aim for the markdown newline (which is a single backslash, correct?):

```plaintext
rake posts:remap["replaceme","\",string,true]

```

I guess I’d have to escape that too?

Any guidance appreciated.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [January 17, 2023, 4:38pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/164 "2023-01-17T16:38:27Z")

</div>

I’d do it in rails where you don’t have to worry about so many levels of quoting.

---

<div class="post-metadata">

### Author: ![MiG](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mig/32/119486_2.png) [@MiG](https://meta.discourse.org/u/MiG)
#### Post date: [January 17, 2023, 7:13pm UTC](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729/165 "2023-01-17T19:13:33Z")

</div>

Good idea. Escaping things makes my head hurt.

I see your code above is easy enough. Something like this?

```plaintext
Topics.where(category_id: 123).each do |t|
  posts.where(topic_id: t).each do |p|
    p.raw.gsub("replaceme","/")
  end
end

```

Something like that? I assume the markdown / is better than using CR/LF or \n, or even   
 or whatever?

How does one run this from the shell? Just type in “rails” and then copy the code in there?

[Next page](https://meta.discourse.org/t/replace-a-string-in-all-posts/48729.md?page=2)
