109

This question led to a new package:
checkcites

While reading papers, I put those that I'd like to refer to or mention in customized .bib files (one .bib file for each paper). (Thanks to Mendeley it's pretty easy and straight forward - they call it "collections").

My intention is that all entries in the .bib file should be mentioned in the text.

How to check which bibliography entries I have not referred to ?

4
  • If tex code would be helpfull here, or more details, please let me know, I'd love to improve question. Feb 3, 2012 at 13:23
  • 1
    Only those entries \cited will appear in the bibliography. If you want to make a .bib file that consists of only those entries cited, then see this: tex.stackexchange.com/questions/32032/…
    – Seamus
    Feb 3, 2012 at 13:28
  • If you are in a unix-like environment, I can write for you a short script that does exactly what you need. The information on used references is stored in the .aux file in the form \citation{ref-label}.
    – yo'
    Feb 3, 2012 at 13:29
  • Maybe you could extract the cited references from your .bib file using bibexport to a new file and then diff both to see the differences. Feb 3, 2012 at 13:33

7 Answers 7

109

Another way is to use the refcheck package and add \nocite{*} in your document. This package will warn you (amongst other things) about unused references. My MWE:

\begin{filecontents}{\jobname.bib}
@BOOK{foo:2012a,
  title = {My Title One},
  publisher = {My Publisher One},
  year = {2012},
  editor = {My Editor One},
  author = {Author One}
}

@BOOK{foo:2012b,
  title = {My Title Two},
  publisher = {My Publisher Two},
  year = {2012},
  editor = {My Editor Two},
  author = {Author Two}
}

@BOOK{foo:2012c,
  title = {My Title Three},
  publisher = {My Publisher Three},
  year = {2012},
  editor = {My Editor Three},
  author = {Author Three}
}
\end{filecontents}

\documentclass{article}

\usepackage{refcheck}

\begin{document}

Hello world \cite{foo:2012a,foo:2012b}.

\nocite{*}

\bibliographystyle{plain}
\bibliography{\jobname}

\end{document}

The output:

My output

The reference keys not cited in your document will be displayed between ?...?. Besides, refcheck adds the following line to your .log file:

<Info by RefCheck> Unused bibitem `foo:2012c' on page 1.

Hope it helps. :)

Update: Based on this question, egreg and I came up with a Lua script called checkcites. The idea of this script is to detect unused or undefined references from LaTeX auxiliary (.aux) or bibliography (.bib) files.

Consider the following example: document.tex

\begin{filecontents}{\jobname.bib}
@BOOK{foo:2012a,
  title = {My Title One},
  publisher = {My Publisher One},
  year = {2012},
  editor = {My Editor One},
  author = {Author One}
}

@BOOK{foo:2012b,
  title = {My Title Two},
  publisher = {My Publisher Two},
  year = {2012},
  editor = {My Editor Two},
  author = {Author Two}
}

@BOOK{foo:2012c,
  title = {My Title Three},
  publisher = {My Publisher Three},
  year = {2012},
  editor = {My Editor Three},
  author = {Author Three}
}

@BOOK{foo:2012d,
  title = {My Title Four},
  publisher = {My Publisher Four},
  year = {2012},
  editor = {My Editor Four},
  author = {Author Four}
}
\end{filecontents}

\documentclass{article}

\begin{document}

Hello world \cite{foo:2012a,foo:2012c},
how are you \cite{foo:2012e}, and
goodbye \cite{foo:2012d,foo:2012a}.

\bibliographystyle{plain}
\bibliography{\jobname}

\end{document}

After compiling it, an auxiliary file document.aux will be generated. Now we will use texlua (which is available in both MiKTeX and TeX Live distros) to run checkcites on the .aux file:

$ texlua checkcites.lua document.aux

The script will look for all unused and undefined references. The output will be:

checkcites terminal

If you want to look only for unused references in your .bib file, you can add the --unused flag:

$ texlua checkcites.lua --unused document.aux

The argument order doesn't matter, so you can also call:

$ texlua checkcites.lua document.aux --unused 

Similarly, using

$ texlua checkcites.lua --undefined foo.aux

will make the script only look for undefined references in your .tex file.

To look for both unused and undefined references, you can also use the --all flag. If no flag is provided, checkcites will behave as if --all was provided.

The script is now available on CTAN and tlmgr will install it on TeX Live 2011 (or later). Hope you guys like our humble script. :)

Update: As checkcites is now available on CTAN and TeX Live, there's no need of explicitly calling texlua nor the original checkcites.lua file; a simple call to

$ checkcites --unused document.aux

will suffice, since the script is properly wrapped. :)

21
  • Wow, I was not aware of this package before. Pretty elegant!
    – Daniel
    Feb 3, 2012 at 22:56
  • 1
    I just tested it with my Thesis.tex which is divided in several .tex files (I use \included to input each chapter). Sadly, checkcites does not work in this case. A citation in Chap1.tex is logged in Chap1.aux, so there is no record of it in Thesis.aux. I naively tried to run checkcites to Chap1.aux, but it does not have \bibdata with the the name of the .bib, so it won't be able to find the bibliography to compare with. Any ideas? Anyway, it is still a great package. Aug 23, 2012 at 7:50
  • 1
    Hi @Felipe! :) Thanks for the feedback. Currently, checkcites can handle multiple .bib files, but AFAIK only one .aux file. I'll take a look at the code and try to work on an improved version. :) About the output to an external file, a workaround for now would be to redirect the output with $ checkcites mydoc.aux > out.txt. Hope it helps. :) Aug 23, 2012 at 10:15
  • 2
    @thiagowfx: I added support for multiple .aux files, hope it helps! Cheers! Aug 26, 2017 at 10:26
  • 2
    For biblatex users, use the new --backend option, .e.g. checkcites --backend biber document. No need to provide a file extension!
    – ApolloLV
    Jul 20, 2018 at 17:57
21

This question deserves a brief answer to demonstrate how simple checkcites actually is. At your prompt simply type ...

$ checkcites my_document.aux

... and it prints out a nicely formatted list of unused + undefined references.

This works out-of-the-box if you have a full installation of a recent TeX-Live distribution (2011+), where the command checkcites should already by on your path. It's a simple command line tool; no modification in your document is required (e.g. usepackage).

I hope my answer will prevent others to manually download the script from CTAN, study the docs, just to find out that RTFM is overkill in this case :).

17

One possibility would be the following:

  1. Switch the bibtex bibliography style to unsrt (with biblatex pass the sorting=none option)
  2. Compile your document --> PDF with cited references
  3. At the very end of your document (before the \bibliography command) add a \nocite{*}
  4. Compile your document --> PDF with all references
  5. Compare the bibliography of both PDFs. The "extra" entries at the end are those you have not yet cited.

However, if you work in a UNIX-like environment, I would probably use tools like grep and sed to extract the keys from the .aux file and the .bib file and diff them:

cat paper.aux | grep '\\citation' | sed -e 's/\\citation{\(.*\)}/\1/g' -e 's/ *\(.*\) */\1/g' | tr ',' '\012' | sort -u > paper.keys
cat paper.bib | grep "@.*{.*," | sed -e 's/.*{\(.*\),/\1/' | sort -u > bib.keys
grep -v -f paper.keys bib.keys

The first line extracts all keys given in \citation{key1[,key2 ...]} commands from the aux-file into distinct lines, sorts and unifies them (every entry is contained once once) and redirects the result into the file paper.keys. The second line does the same for the keys contained in @<some type>{key, lines in the bib file. The third line prints out every line from bib.keys that is not contained in paper.keys, which is the delta you are interested in.

8
  • Why the four backslashes in the argument to grep? And wouldn't it be simpler starting with grep '\\citation' paper.aux?
    – egreg
    Feb 3, 2012 at 14:39
  • @egreg I think that Daniel took it from me ;) and these things are just a matter of habit I think ;)
    – yo'
    Feb 3, 2012 at 15:04
  • @tohecz Well, on my system it doesn't work with four backslashes.
    – egreg
    Feb 3, 2012 at 15:06
  • @egreg: tohecz an me discussed how to build this line in another question, he is right that I took the grep part from him. The point is: If you put the parameter in double quotes, the shell will substitute them down to two backslashes and grep down to one. If you put it in single quotes (which you probably tried) the shell will not perform substitution, so four backslashes are passed to grep, hence the pattern does not match. I have modified the solution to use single quotes.
    – Daniel
    Feb 3, 2012 at 16:37
  • @egreg: I prefer cat <file> | grep <expression> just because it is then more visible which <file> I am working on (especially if <expression> is nontrivial). This is slightly slower, though.
    – Daniel
    Feb 3, 2012 at 16:40
10

Given that you are using bibtex and not biblatex, the Bibtool utility may be able to help you. Say you have a myreferences.bib file you've created in Mendeley or wherever. You write paper.tex with the intention of explicitly citing every item from myreferences.bib. To see if you've forgotten anything, use bibtool to extract a bibliography of all and only the references cited in paper.tex and compare its contents to the original:

bibtool -x paper.aux -o paperrefs.bib

Now you can compare paperrefs.bib to myreferences.bib:

diff myreferences.bib paperrefs.bib

Ideally you'll find there's no difference. You could probably work this up into a script of the sort mentioned by tohecz, but using bibtool means you don't have to come up with a regular expression to catch the various forms of citation. Your original myreferences.bib should be sorted alphabetically for this to work properly.

5

This answer will give you a clue, but only for biblatex, I believe. (I won't duplicate it here)

It allows you to use \nocite{*} to place all the unreferenced .bib file entries in a separate section of the bibliography.

Normally, one might publish this as 'additional reading', for example, but in your case you can use it to help prune your .bib file.

1
  • 1
    This works only with biblatex. I don't think that the OP uses biblatex ... P.S. I guess you mean \nocite{*} instead of \nocite(*)
    – Thorsten
    Feb 3, 2012 at 13:36
5

Under unix-like systems, you can make a following bash script, called e.g. diffrefs:

#!/bin/bash
f=${1%.???}
cat $f.aux | grep "\\\\citation" | sed -e 's/\\citation{\(.*\)}/\1/g' -e 's/,/\n/g' -e 's/ *\(.*\) */\1/g' | sort | uniq > $f.cit
# cat $f.aux | grep "\\\\citation" | sed -e 's/\\citation{\(.*\)}/\1/g' -e 's/ *\(.*\) */\1/g' | sort | uniq > $f.cit
cat $f.bib | grep "^@" | sed 's/.*{\|,.*//g' | sort >$f.bit
echo "Unused but defined references:"
diff $f.cit $f.bit | grep "^>"
echo "Undefined but used references:"
diff $f.cit $f.bit | grep "^<"

Usage: diffrefs myfile

Explanation:

  • cat $f.aux ...: outputs the auxiliary file (cat), takes the information on used citations (grep), extracts the labels, removes white-space (sed), sorts and removes duplicates (sort, uniq)
  • cat $f.bib ...: outputs the bibtex file (cat), takes the first line of each entry (grep) removes evertything before { and after , (sed), and does sort, uniq as before.
  • diff ...: prints differences between two files, the characters < and > say "which file is larger by that line"

Edit: I found that LaTeX automatically perorms the comma-seperation of \cite{...} parameter, so I removed it from the script.

Edit: In 2021 the code of the previous version works with elsarticle (restored with the other version commented #)
The script requires the same name for the .tex and .bib files (in case use ln -s mybib.bib LaTeXFileName.bib).

1
  • 1
    No, the argument to \citation can contain commas, depending on the package used for citation, for instance natbib.
    – egreg
    Feb 3, 2012 at 14:43
1

Since I ran into some issues with the refcheck package, a rather simple option would be to load hyperref with the pagebackref option. Then, doing a \nocite{*} in the main TeX file, the bibliography gets back references to the pages where an entry was cited. No citation -> no back reference.

\begin{filecontents}{\jobname.bib}
@BOOK{foo:2012a,
  title = {My Title One},
  publisher = {My Publisher One},
  year = {2012},
  editor = {My Editor One},
  author = {Author One}
}

@BOOK{foo:2012b,
  title = {My Title Two},
  publisher = {My Publisher Two},
  year = {2012},
  editor = {My Editor Two},
  author = {Author Two}
}

@BOOK{foo:2012c,
  title = {My Title Three},
  publisher = {My Publisher Three},
  year = {2012},
  editor = {My Editor Three},
  author = {Author Three}
}
\end{filecontents}

\documentclass{article}

\usepackage[pagebackref]{hyperref}

\begin{document}

Hello world \cite{foo:2012a,foo:2012b}.

\nocite{*}

\bibliographystyle{plain}
\bibliography{\jobname}

\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .