I have a text file that contains a long list of entries (one on each line). Some of these are duplicates, and I would like to know if it is possible (and if so, how) to remove any duplicates. I am interested in doing this from within vi/vim, if possible.
-
1Looks like a duplicate of http://stackoverflow.com/questions/746689/unix-tool-to-remove-duplicate-lines-from-a-file – Nathan Fellman Feb 18 '10 at 21:01
-
5This one is 1 year old; that one is 10 months. So, other way around. – Sydius Feb 26 '10 at 19:50
-
@Sydius consensus now is to prioritize upvote count (which you also have more of): http://meta.stackexchange.com/questions/147643/should-i-vote-to-close-a-duplicate-question-even-though-its-much-newer-and-ha And those are not duplicates, that one does not mention Vim :-) – Ciro Santilli OurBigBook.com Aug 08 '16 at 08:38
14 Answers
If you're OK with sorting your file, you can use:
:sort u

- 71,150
- 28
- 166
- 168
-
24If sorting is unacceptable, use ``:%!uniq`` to simply remove duplicate entries without sorting the file. – cryptic0 Mar 06 '18 at 14:39
-
once you use the command the whole file changes? how do you go back? I already saved the file by mistake ... my bad – nilon May 04 '18 at 14:51
-
Just use [Vim's undo command](http://vimdoc.sourceforge.net/htmldoc/undo.html): `u` – adampasz Aug 11 '19 at 00:23
-
@adampasz but I already closed the file and it does not seem to remember data from the last session. (This is a downside of always closing files while saving by just pressing `ZZ`.) – nilon Feb 25 '21 at 18:16
-
@cryptic0, uniq won't work unless the duplicates are sorted `a$b$a$` does nothing – CervEd May 02 '21 at 17:58
-
@nilon, that's when using persistent undo comes in handy https://stackoverflow.com/questions/5700389/using-vims-persistent-undo – egst Oct 14 '22 at 09:54
-
You can select the lines you want sorted and deduplicated first with `V` or something similar, then issue the command. – Lorenz Leitner May 11 '23 at 12:32
Try this:
:%s/^\(.*\)\(\n\1\)\+$/\1/
It searches for any line immediately followed by one or more copies of itself, and replaces it with a single copy.
Make a copy of your file though before you try it. It's untested.
-
1@hop Thanks for testing it for me. I didn't have access to vim at the time. – Sean Dec 09 '08 at 20:50
-
2this hightlights all the duplicate lines for me but doesn't delete, am I missing a step here? – ak85 Sep 14 '12 at 23:57
-
I'm pretty sure this will also highlight a line followed by a line that has the same "prefix" but is longer. – hippietrail Apr 29 '15 at 01:47
-
This is the better solution and doesn't change the line numbers as well. Thanks – Amir Oct 02 '17 at 05:44
-
3The only issue with this is that if you have multiple duplicates (3 or more of the same lines), you have to run this many times until all dups are gone since this only removes them one set of dups at a time. – horta Jan 22 '18 at 23:56
-
-
2Another drawback of this: this won't work unless your duplicate lines are already next to each other. Sorting first would be one way of ensuring they're next to each other. At that point, the other answers are probably better. – horta Mar 09 '19 at 22:42
From command line just do:
sort file | uniq > file.new
-
2
-
1Couldn't get the accepted answer to work, as `:sort u` was hanging on my large file. This worked very quickly and perfectly. Thank you! – TayTay Mar 23 '15 at 15:50
-
1`'uniq' is not recognized as an internal or external command, operable program or batch file.` – hippietrail Apr 29 '15 at 01:49
-
2Yes -- I tried this technique on a 2.3 GB file, and it was shockingly quick. – DanM Feb 06 '17 at 19:46
-
@hippietrail You are on windows PC? Maybe you can use cygwin. – 12431234123412341234123 May 08 '18 at 12:55
awk '!x[$0]++' yourfile.txt
if you want to preserve the order (i.e., sorting is not acceptable). In order to invoke it from vim, :!
can be used.

- 445
- 1
- 4
- 12
-
4This is lovely! Not needing to sort is *exactly* what I was looking for! – Cometsong Oct 13 '17 at 16:36
-
-
This can also be done in perl if it strikes your fancy `perl -nle 'print unless $seen{$_}++' yourfile.txt` – Billious Mar 30 '23 at 19:43
g/^\(.*\)$\n\1/d
Works for me on Windows. Lines must be sorted first though.

- 529
- 5
- 15
-
1This will delete a line following a line which is it's prefix: `aaaa` followed by `aaaabb` will delete `aaaa` erroneously. – hippietrail Apr 29 '15 at 01:51
I would combine two of the answers above:
go to head of file
sort the whole file
remove duplicate entries with uniq
1G
!Gsort
1G
!Guniq
If you were interested in seeing how many duplicate lines were removed, use control-G before and after to check on the number of lines present in your buffer.

- 533
- 5
- 9
-
1`'uniq' is not recognized as an internal or external command, operable program or batch file.` – hippietrail Apr 29 '15 at 01:48
If you don't want to sort/uniq the entire file, you can select the lines you want to make uniq in visual mode and then simply: :sort u
.

- 41
- 3
-
If you know the line numbers you want sorted to unique you can prefix the starting and ending line numbers, eg. if you want to sort+unique lines 5 through 10 the command would be `:5,10 sort u` – Billious Mar 30 '23 at 19:39
Select the lines in visual-line mode (Shift+v), then :!uniq
. That'll only catch duplicates which come one after another.
-
1Just to note this will only work on computers with the uniq program installed i.e. Linux, Mac, Freebsd etc – anteatersa Feb 11 '14 at 11:26
-
This will be the best answer to those who don't need sorting. And if you are windows user, consider to try Cygwin or MSYS. – fx-kirin Jun 30 '16 at 04:44
Regarding how Uniq can be implemented in VimL, search for Uniq in a plugin I'm maintaining. You'll see various ways to implement it that were given on Vim mailing-list.
Otherwise, :sort u
is indeed the way to go.

- 31,979
- 7
- 69
- 83
:%s/^\(.*\)\(\n\1\)\+$/\1/gec
or
:%s/^\(.*\)\(\n\1\)\+$/\1/ge
this is my answer for you ,it can remove multiple duplicate lines and only keep one not remove !

- 129
- 7
I would use !}uniq
, but that only works if there are no blank lines.
For every line in a file use: :1,$!uniq
.

- 155,785
- 88
- 678
- 743

- 2,920
- 15
- 10
This version only removes repeated lines that are contigous. I mean, only deletes consecutive repeated lines. Using the given map the function does note mess up with blank lines. But if change the REGEX to match start of line ^
it will also remove duplicated blank lines.
" function to delete duplicate lines
function! DelDuplicatedLines()
while getline(".") == getline(line(".") - 1)
exec 'norm! ddk'
endwhile
while getline(".") == getline(line(".") + 1)
exec 'norm! dd'
endwhile
endfunction
nnoremap <Leader>d :g/./call DelDuplicatedLines()<CR>

- 11,069
- 3
- 50
- 40
An alternative method that does not use vi/vim (for very large files), is from the Linux command line use sort and uniq:
sort {file-name} | uniq -u

- 459
- 6
- 10
This worked for me for both .csv
and .txt
awk '!seen[$0]++' <filename> > <newFileName>
Explanation: The first part of the command prints unique rows and the second part i.e. after the middle arrow is to save the output of the first part.
awk '!seen[$0]++' <filename>
>
<newFileName>

- 4,333
- 16
- 71
- 144