Recently, I decided to switch my primary password manager to 1Password , using it across my Macbooks and Pixel phones on various browsers, including Firefox and Chrome. One bonus feature that I particularly enjoy is its compatibility with Alfred , an app that helps me be more productive on my Mac.
However, the transition was not all smooth sailing. When I transferred my passwords from Firefox and Chrome into 1Password, a couple of things didn’t go quite right. I ended up with:
- Lots of records that had the website’s URL saved as the username and my actual username saved as the password.
- A cluttered 1Password account with lots of duplicate records – each one with the same website, username, and password.
Naturally, manually going through hundreds of passwords to sort this out was not my idea of a fun time. Thankfully, 1Password provides a CLI tool, and with a little learning and scripting, I was able to address both issues.
To get started, I needed to install the 1Password CLI and sign in . I also needed to have jq installed on my machine.
To remove items where the username is actually a URL, I created a bash script:
for id in $(op item list --format=json | jq -r '.[] | select(.id != null) | .id'); do
item=$(op item get $id --format=json)
if [[ $item != null ]]; then
fields=$(echo $item | jq -r '.fields')
if [[ $fields != null ]]; then
username=$(echo $fields | jq -r '.[] | select(.label=="username").value')
if [[ $username == http* ]]; then
op item delete $id --archive
echo "$id deleted"
fi
fi
fi
done
Then, I made my script executable and ran it:
chmod +x remove-urls.sh
./remove-urls.sh
The first issue is resolved!
Next, I addressed the problem of duplicate entries. To do this, I had to first update Bash to a more recent version that could handle special types of lists called associative arrays. Because I was using a Mac, it initially came with an older version of Bash that lacked this feature (bash --version
gave me v3.2). So, my first step was to install a newer version of Bash (v5.2):
brew install bash
And find its path:
which bash
Then, used the path for running the new script to remove duplicates:
#!/opt/homebrew/bin/bash
declare -A itemMap
for id in $(op item list --categories Login --format=json | jq -r '.[] | select(.id != null) | .id'); do
item=$(op item get $id --format=json)
if [[ $item != null ]]; then
fields=$(echo $item | jq -r '.fields')
if [[ $fields != null ]]; then
username=$(echo $fields | jq -r '.[] | select(.label=="username").value')
fi
urls=$(echo $item | jq -r '.urls')
href=$(echo $urls | jq -r '.[0].href')
website=$(echo $href | awk -F[/:] '{print $4}')
if [[ -n $website && -n $username ]]; then
key="$website-$username"
if [[ ${itemMap[$key]} ]]; then
echo "Duplicate found:"
echo "Item 1: id: ${itemMap[$key]}, username: $username, website: $website"
echo "Item 2: id: $id, username: $username, website: $website"
op item delete $id --archive
echo "$id deleted"
else
itemMap[$key]=$id
fi
fi
fi
done
Just as before, I needed to make this script executable and then ran it:
chmod +x remove-duplicates.sh
./remove-duplicates.sh
And the duplicates were gone! Note that in both scripts I used --archive
to ensure I’m not totally deleting the records, just storing them away, so I can bring them back later if necessary. I hope this guide helps those of you who might be having the same issues with 1Password.