6

As most of you may know, there are many acceptable ways of writing authors names. However, when I export .bib entries from software like Zotero (which sometimes exports Last, First names and sometimes First Last names) or JabRef (which exports fields the way you first entered them) or from the Internet, I get authors names in many different ways. Although these sources rarely provide them in incorrect or unusable ways, I'd like to normalize my .bib files so that I can Ctrl + F authors names easily, fill in their names if they are abbreviated and so on.

I am trying to use BibTool, which I already use to clean, format and sort my files. I've tried the following rules in my .bibtoolrsc file:

new.format.type = {17="%f%v%l%j"}
new.format.type = {17="%0f%0v%0l%0j"}
new.format.type = {17="%0f %0v %0l %0j"}

but when I run the bibtool command, all of my other rules work, except these ones (I've tried them separately, of course).

Here is an example of what I want. I wanted something like this:

author = {Brown, Noam and Sandholm, Tuomas}

to become this:

author = {Noam Brown and Tuomas Sandholm}

Does anyone know how to achieve this? I would prefer if I could use BibTool for everything, but if someone recommends some other command, that is acceptable too.

Edit: here is my the content of my .bibtoolrsc file.

  • According to the bibtool documentation, you should not have = before the brace, so just new.format.type {17=....} – Andrew Swann Feb 17 '17 at 8:22
  • 1
    Your attempt to sanitize is going in the wrong direction, I think: better practice is Brown, Noam and Sandholm, Tuomas. – jon Feb 17 '17 at 15:30
  • @AndrewSwann I've tried with and without the equals sign. Still, my other rules work, except for this one. – Douglas De Rizzo Meneghetti Feb 18 '17 at 17:15
  • There are spaces in the linked file not shown in your snippet here. Do they make a difference? – Andrew Swann Feb 18 '17 at 17:35
  • Neither the presence of spaces before or after the equals sign nor the presence of an equals sign between an entry name and the opening curly brace affect the running of the program. The presence of spaces after opening the curly brace and before closing it also changes nothing. – Douglas De Rizzo Meneghetti Feb 20 '17 at 7:24
1

Here is my attempt with a Python script using bibtexparser (note, it will replace the .bib files in-place! Modify the script if you do not want that):

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, sys
import re

import bibtexparser
from bibtexparser.bwriter import BibTexWriter
from bibtexparser.bibdatabase import BibDatabase
from bibtexparser.customization import convert_to_unicode
from bibtexparser.bparser import BibTexParser
import inspect, pprint

# kill stdout terminal buffering
buf_arg = 0
if sys.version_info[0] == 3:
  os.environ['PYTHONUNBUFFERED'] = '1'
  buf_arg = 1
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buf_arg)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', buf_arg)

# EDIT FOR YOUR FILES - relative to current working dir
mybibfiles = ["path1/file1.bib", "path2/file2.bib"]

numcommas = 0
# homogenize_fields: Sanitize BibTeX field names, for example change `url` to `link` etc.
tbparser = BibTexParser()
tbparser.homogenize_fields = False  # no dice
tbparser.alt_dict['url'] = 'url'    # this finally prevents change 'url' to 'link'

for bibfile in mybibfiles:
  print((bibfile, os.path.isfile(bibfile)))
  with open(bibfile) as bibtex_file:
    bibtex_str = bibtex_file.read()
  bib_database = bibtexparser.loads(bibtex_str, tbparser)
  pprint.pprint(bib_database.entries) # already here, would by default replace 'url' with 'link'!
  bibdblen = len(bib_database.entries)
  for icpbe, paperbibentry in enumerate(bib_database.entries):
    authstr = paperbibentry['author']
    if ("," in authstr):
      numcommas += 1
      report = "%d/%d: Comma present: '%s'"%(icpbe+1, bibdblen, authstr)
      authstrauthors = authstr.split(" and ")
      for ia, author in enumerate(authstrauthors):
        if ("," in author):
          authorparts = author.split(", ")
          # the first part [0] is last name, needs to become last
          # get and remove the first part, then append it as last
          lastname = authorparts.pop(0)
          authorparts.append(lastname)
          authorfirstlast = " ".join(authorparts)
          authstrauthors[ia] = authorfirstlast
      paperbibentry['author'] = " and ".join(authstrauthors)
      bib_database.entries[icpbe] = paperbibentry
      report += " -> '%s'"%(paperbibentry['author'])
    else:
      report = "%d/%d: OK"%(icpbe+1, bibdblen)
    if sys.version_info[0] == 3:
      print(report)
    else: #python 2
      print(report.encode('utf-8'))
  with open(bibfile, 'w') as thebibfile:
    bibtex_str = bibtexparser.dumps(bib_database)
    if sys.version_info[0]<3: # python 2
      thebibfile.write(bibtex_str.encode('utf8'))
    else: #python 3
      thebibfile.write(bibtex_str)

print("\nFound & converted total of %d author fields in format Last, First (with commas)."%(numcommas))
1

In trying to solve the same problem almost a year later, I found out that JabRef has an option called "Cleanup entries" under the "Quality" menu. If one adds the rule "Normalize names of persons" for the "author" and/or "editor" fields, JabRef normalizes names in the "von Last, Jr., First" format. Not exactly what the original question asks for, but since it homogenizes the way all name fields are represented in a bib file, I think it's worth mentioning.

JabRef also points out which entries are out of spec by using the "Quality" > "Check integrity" option.

It doesn't work with Bibtex extended name format (see section 3.8 of the biber manual for what that is).

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.