6

When citing items using BibTeX, only the cited items show up in the bibliography (unless you use \nocite{*}). Can I have the same effect for normal \bibitems that are at the end of my .tex file? (I have a long list that I use for several longer reports.)

  • 5
    If the bibliography items are listed verbatim as \bibitems and you're not using a bibliography manager like BibTeX or BibLaTeX, then there's not much you can do... all the items will be set regardless of whether they're \cited or not. As such, removing \nocite{*} would not make any difference. "Not much" means there might be other methods, but it's just not as easy. – Werner Oct 12 '16 at 5:54
  • 3
    The usual method is to make your collection of references as a .bib file (bibtex "database") and then the job of extracting just the used citations is exactly what bibtex (and now biber) are designed to do. \nocite does nothing if you are not using bibtex. – David Carlisle Oct 12 '16 at 7:06
  • 1
    Short answer: No. If you are doing stuff manually, you have to do stuff manually. – Johannes_B Oct 12 '16 at 8:11
  • 2
    A manual solution, but you can use the refcheck package to quickly identify which items from the bibliography are actually cited, and then comment out those you don't use. – Andrew Swann Oct 12 '16 at 8:17
  • 2
    @domotorp Not really, as there's no end marker for \bibitem so collecting stuff up would be non-trivial. Moreover, the interest in developing such a solution is likely to be low as using a .bib database and either BibTeX or Biber is very common and is selective. – Joseph Wright Oct 12 '16 at 8:31
6

If you are prepared to accept that \bibitem should be ended by a blank line, then you can modify some of the code from source2e and refcheck to make this work. You have run latex three times to get the correct numbering in the text.

Sample output

\documentclass{article}

\makeatletter
\let\@@citation@@=\citation

\renewcommand{\citation}[1]{\@@citation@@{#1}%
\@for\@tempa:=#1\do{\@ifundefined{cit@\@tempa}%
  {\global\@namedef{cit@\@tempa}{}}{}}%
}

\def\@lbibitem[#1]#2#3\par{%
  \@ifundefined{cit@#2}{}{\item[\@biblabel{#1}\hfill]}%
  \if@filesw
      {\let\protect\noexpand
       \immediate
       \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces
  \@ifundefined{cit@#2}{}{#3}}
\def\@bibitem#1#2\par{%
  \@ifundefined{cit@#1}{}{\item}%
  \if@filesw \immediate\write\@auxout
    {\string\bibcite{#1}{\the\value{\@listctr}}}\fi\ignorespaces
  \@ifundefined{cit@#1}{}{#2}}
\makeatother

\begin{document}

Test a citation \cite{one} and another \cite{three}.  Also one more
for luck: \cite{five}.

\begin{thebibliography}{9}

\bibitem{one} Reference one.

\bibitem{two} Reference two.

\bibitem[Special]{three} Reference three.

\bibitem{four} Reference four.

\bibitem{five} Reference five.

\bibitem[Unusual]{six} Reference six.

\end{thebibliography}

\end{document}

The first part of the code is refchecks modification to the \cite command so that use of a bibitem is recorded. The second part is a modification of the core latex \bibitem, so that it always records the label in the .aux file, but only prints out the body if the item has been cited.

If you need to use this with hyperref so there are links to the bibliography, then the coding has to be adapted to hyperref's versions on \@lbibitem and \@bibitem, since hyperref simply overwrites the current definition. This is given as follows, notice the positioning of the loading of the hyperref package:

\documentclass{article}

\makeatletter
\let\@@citation@@=\citation

\renewcommand{\citation}[1]{\@@citation@@{#1}%
\@for\@tempa:=#1\do{\@ifundefined{cit@\@tempa}%
  {\global\@namedef{cit@\@tempa}{}}{}}%
}
\makeatother

\usepackage{hyperref}

\makeatletter
\def\@lbibitem[#1]#2#3\par{%
  \@ifundefined{cit@#2}{}{\@skiphyperreftrue
  \H@item[%
    \ifx\Hy@raisedlink\@empty
      \hyper@anchorstart{cite.#2\@extra@b@citeb}%
        \@BIBLABEL{#1}%
      \hyper@anchorend
    \else
      \Hy@raisedlink{%
        \hyper@anchorstart{cite.#2\@extra@b@citeb}\hyper@anchorend
      }%
      \@BIBLABEL{#1}%
    \fi
    \hfill
  ]%
  \@skiphyperreffalse}%
  \if@filesw
    \begingroup
      \let\protect\noexpand
      \immediate\write\@auxout{%
        \string\bibcite{#2}{#1}%
      }%
    \endgroup
  \fi
  \ignorespaces
  \@ifundefined{cit@#2}{}{#3}}

\def\@bibitem#1#2\par{%
  \@ifundefined{cit@#1}{}{\@skiphyperreftrue\H@item\@skiphyperreffalse
  \Hy@raisedlink{%
    \hyper@anchorstart{cite.#1\@extra@b@citeb}\relax\hyper@anchorend
    }}%
  \if@filesw
    \begingroup
      \let\protect\noexpand
      \immediate\write\@auxout{%
        \string\bibcite{#1}{\the\value{\@listctr}}%
      }%
    \endgroup
  \fi
  \ignorespaces
  \@ifundefined{cit@#1}{}{#2}}
\makeatother

\begin{document}

Test a citation \cite{one} and another \cite{three}.  Also one more
for luck: \cite{five}.

\begin{thebibliography}{9}

\bibitem{one} Reference one.

\bibitem{two} Reference two.

\bibitem[Special]{three} Reference three.

\bibitem{four} Reference four.

\bibitem{five} Reference five.

\bibitem[Unusual]{six} Reference six.

\end{thebibliography}

\end{document}
  • Thanks, this seems to work! I still have one error message tough. Should I have a blank line before and after each \bibitem? – domotorp Oct 12 '16 at 10:59
  • OK, after half an hour I've figured out that I need a linebreak also after the last \bibitem which was there in bibliography.tex, but after I input it in the main file, it apparently gets ignored, so a linebreak is needed in the main file after the input. – domotorp Oct 12 '16 at 11:18
  • You just need each \bibitem to end with a blank line (or a \par) – Andrew Swann Oct 12 '16 at 11:28
  • 1
    @domotorp Well, to get clickable links you have to load the hyperref package. As usual make sure you do this as late as possible in your preamble, in particular after the modifications above. Then it works for me. – Andrew Swann Oct 17 '16 at 9:36
  • 1
    @domotorp Update for working with hyperref now provided. – Andrew Swann Oct 18 '16 at 14:35
2

You could change your input format to put the text in an argument. Then it is rather easy to suppress one entry:

\documentclass{article}
\usepackage{xpatch}
\makeatletter
\xpretocmd\@citex{\csgdef{used@cite@#2}{x}}{}{\failed}
\newcommand\checkbibentry[2]{\ifcsdef{used@cite@#1}{\bibitem{#1}{#2}}{}}
\makeatletter
\begin{document}

\cite{a} \cite{c}

\begin{thebibliography}{99}

\checkbibentry{a}{some text to a}

\checkbibentry{b}{some text to b}

\checkbibentry{c}{some text to c}
\end{thebibliography}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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