# FILENAME: abbrv_bib.py
#!/usr/bin/env python3
from bibtexparser.bwriter import BibTexWriter
import bibtexparser
from pybtex.database import parse_file
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('input', help='input file name')
parser.add_argument('output', help='output file name')
parser.add_argument('--no-middle', action='store_true',
help='do not abbreviate middle name')
args = parser.parse_args()
# %%
# Parse the original bib file with pybtex
# pybtex can distinguish first/middle/last names
bib_database = parse_file(args.input)
for k in bib_database.entries.keys():
item = bib_database.entries[k]
persons = item.persons
print(k)
for i in range(len(persons['author'])):
oldFirstNames = persons['author'][i].first_names
newFirstNames = []
for j in oldFirstNames:
if j[-1] == '.':
newFirstNames.append(j)
else:
newFirstNames.append(j[0].upper() + '.')
oldMiddleNames = persons['author'][i].middle_names
if args.no_middle:
newMiddleNames = oldMiddleNames[:]
else:
newMiddleNames = []
for j in oldMiddleNames:
if j[-1] == '.':
newMiddleNames.append(j)
else:
newMiddleNames.append(j[0].upper() + '.')
oldName = ' '.join(
[' '.join(persons['author'][i].last_names) + ','] + oldFirstNames + oldMiddleNames)
newName = ' '.join(
[' '.join(persons['author'][i].last_names) + ','] + newFirstNames + newMiddleNames)
if (oldName != newName):
print(' - {:s} => {:s}'.format(oldName, newName))
persons['author'][i].first_names = newFirstNames
persons['author'][i].middle_names = newMiddleNames
# %%
# Write the new bib file with bibtexparser
# I use bibtexparser here because pybtex prefers quote instead of curly bracket
# e.g. pybtex: title = "This is a paper"
# bibtexparser: title = {This is a paper}
# This makes it escape some underscores incorrectly
with open(args.input, 'r', encoding='utf-8') as bibtex_file:
bibtex_str = bibtex_file.read()
bib = bibtexparser.loads(bibtex_str)
for k in bib.entries_dict:
bib.entries_dict[k]['author'] = ' and '.join(['{:s}, {:s} {:s}'.format(' '.join(p.last_names), ' '.join(p.first_names), ' '.join(p.middle_names))
for p in bib_database.entries[k].persons['author']])
writer = BibTexWriter()
with open(args.output, 'w', encoding='utf-8') as bibfile:
bibfile.write(writer.write(bib))
I wrote a python script to do it manually. This avoids incompatibility of biblatex to other package. You can use it as
python3 abbrv_bib.py input.bib output.bib
If you don't want to abbreviate middle name, just add the argument --no-middle
The script can abbreviate the following types of name:
Cruden, Brett A. => Cruden, B. A.
Johann Sebastian Bach => Bach, J. S.
Surname, Given Name III. => Surname, G. N. III.
Johann Sebastian Jr. Bach => Bach, J. S. Jr.
It also rearrange the name to Last name, First name Middle name
makebst
. It supports making first names into initials.