Skip to the content.

PS4 PKG Title Renamer

Rename PS4 .pkg files and CUSA title-ID folders to game names, automatically. ps4-pkg-title-renamer reads the param.sfo inside each PS4 PKG. From it, the script gets the game title, title ID, type (base game, patch or DLC), version and content ID, and uses them to give every file and folder a clear, consistent name. It’s a small Python script with no dependencies, and it runs on Linux, macOS and Windows.

CUSA00900/                                   Bloodborne [CUSA00900]/
├── CUSA00900_base.pkg                ->     ├── Bloodborne [CUSA00900] [v1.00] [base].pkg
├── update.pkg                               ├── Bloodborne [CUSA00900] [v1.09] [patch].pkg
└── Bloodborne The Old Hunters.pkg           └── Bloodborne The Old Hunters [CUSA00900] [v1.00] [dlc].pkg
CUSA11253_base.pkg  (loose in root)          Dead Cells [CUSA11253]/
                                             └── Dead Cells [CUSA11253] [v1.00] [base].pkg

Example with --add-id --add-version. The default is just Bloodborne [base].pkg, and every tag is optional.

Features

Contents

Prerequisites

Requirement Why
Python 3.8+ Runs the script. Only the standard library is used, so there’s nothing to pip install
git Clones and updates the repo
Internet access Only needed for the English-name lookup in --build-db. Use --offline to skip it

The prerequisites are also listed in requirements.txt, which names no packages, and checked by install_prereqs.sh (Linux/macOS) or install_prereqs.ps1 (Windows).

Installation

Linux / macOS

# 1. get git if you don't have it (Debian/Ubuntu shown; the script below handles other distros)
sudo apt-get update && sudo apt-get install -y git

# 2. clone the repo
git clone https://github.com/bsgonzalezq/ps4-pkg-title-renamer.git
cd ps4-pkg-title-renamer

# 3. install / verify Python 3.8+ and git (apt, dnf, pacman, zypper or Homebrew)
./install_prereqs.sh

install_prereqs.sh installs only what’s missing, checks the Python version, and runs pip install -r requirements.txt if packages are ever added there.

If you’d rather install by hand:

Distro Command
Debian / Ubuntu sudo apt-get install -y python3 git
Fedora / RHEL sudo dnf install -y python3 git
Arch sudo pacman -S --needed python git
openSUSE sudo zypper install -y python3 git
macOS (Homebrew) brew install python git

Windows

winget install -e --id Git.Git          # skip if git is installed
# reopen the terminal so git is on PATH, then:
git clone https://github.com/bsgonzalezq/ps4-pkg-title-renamer.git
cd ps4-pkg-title-renamer
powershell -ExecutionPolicy Bypass -File .\install_prereqs.ps1   # installs / checks Python 3.8+ and git
py ps4_rename.py --help

install_prereqs.ps1 works like install_prereqs.sh: it installs only what’s missing (through winget), checks the Python version, and checks the script runs.

Using the script on Windows:

Updating

cd ps4-pkg-title-renamer
git pull

If you keep a copy of ps4_rename.py somewhere else, such as next to your games, copy it over again after pulling.

Quick start

The script always lives in a folder named ps4-pkg-title-renamer, together with its db (ps4_titles.db) and all its logs:

The examples use relative paths.

The script takes one optional PATH: the folder that holds your PKG folders. With no PATH it works on the current directory. PATH can be relative or absolute.

Both examples use this layout, with the script in a subfolder of the games folder:

games/                  <- games folder (holds the PKG folders)
├── CUSA00900/
├── CUSA00419/
└── ps4-pkg-title-renamer/  <- script folder (a clone of this repo, or created automatically)
    ├── ps4_rename.py
    ├── ps4_titles.db
    └── rename_undo.log, rename_results_*.log

Option 1: your terminal is in the games folder (games/). No PATH is needed because the current directory is already the games folder:

cd games
python3 ps4-pkg-title-renamer/ps4_rename.py --build-db   # 1. create ps4_titles.db (optional, done automatically)
python3 ps4-pkg-title-renamer/ps4_rename.py              # 2. dry run: shows what would change
python3 ps4-pkg-title-renamer/ps4_rename.py --apply      # 3. rename
python3 ps4-pkg-title-renamer/ps4_rename.py --undo       #    revert everything, if needed
python3 ps4-pkg-title-renamer/ps4_rename.py --undo-last  #    or preview reverting just the last run (see Undo)

Option 2: your terminal is in the script folder (games/ps4-pkg-title-renamer/). Pass .., the parent folder, as PATH:

cd games/ps4-pkg-title-renamer
python3 ps4_rename.py .. --build-db
python3 ps4_rename.py ..
python3 ps4_rename.py .. --apply
python3 ps4_rename.py .. --undo
python3 ps4_rename.py .. --undo-last

The db and all logs are always kept in the script’s folder, whichever PATH you process, so one db serves all your game folders.

Optional: to run it as just ps4_rename.py from anywhere, run this from the script’s folder to link it into your PATH:

mkdir -p ~/.local/bin && ln -sf "$PWD/ps4_rename.py" ~/.local/bin/ps4_rename.py

Re-run the link command if you move the script.

Options

Option Description
PATH Directory to process (default: current directory)
--apply Perform the renames (default is a dry run)
--undo Revert all renames under PATH recorded in rename_undo.log
--undo-last Revert only the most recent --apply run. Previews unless --apply is added
--undo-match TEXT Revert only renames whose path contains TEXT. Previews unless --apply is added
--add-id Add the title ID tag after the title: Bloodborne [CUSA00900] [patch].pkg. --keep-id still works as an old name for it
--no-title Leave the game title out of .pkg file names; folders keep it. Needs --add-id or --add-content-id. The first part is written without brackets: CUSA00900 [patch].pkg
--add-version Add the PKG version to .pkg names: Bloodborne [v1.09] [patch].pkg
--add-content-id Add the content ID to .pkg names: Bloodborne [UP9000-CUSA00900_00-BLOODBORNE000000] [base].pkg
--no-type Leave out the [base] / [patch] / [dlc] tag: Bloodborne [v1.09].pkg
--order PARTS Order of the parts in .pkg file names, e.g. --order id,title gives [CUSA00900] Bloodborne [patch].pkg. See File part order
--add-region Add the region tag after the title/ID: Bloodborne [CUSA00900] [USA] [patch].pkg
--add-console Add the console tag (PS4, PS5, …, from the db) after the region: Bloodborne [PS4] [patch].pkg
--sep SEP Use SEP instead of spaces in generated names: --sep _ gives Grand_Theft_Auto_V_[patch].pkg. "" means no separator
--no-brackets Write tags without [ ]: Bloodborne CUSA00900 v1.09 patch.pkg
--build-db Add games to the db from the .pkg files in PATH
--rebuild With --build-db: start a fresh db, dropping old entries
--offline Skip the English-name lookup when building the db
--no-auto-db Don’t build the db automatically when IDs are missing
--db FILE Title db to use (see below)
--log FILE Where to write the results log (default: the script’s folder)
--keep-logs N Number of results logs to keep; older ones are deleted. Default 5, and 0 keeps all
--export-xlsx [FILE] Export the db as an Excel workbook and exit. The default file is ps4_titles.xlsx next to the db. See Using the db
--clean-logs Delete the results logs; rename_undo.log is kept
-h, --help Show help

Title database

ps4_titles.db is a plain-text file next to the script. It has two sections, and you can edit both by hand:

# GAMES: TitleID|Title|Region|Console
CUSA00900|Bloodborne™|USA|PS4
CUSA07439|DARK SOULS™ III|EUR|PS4
CUSA10207|Battle Garegga Rev.2016|ASIA|PS4
PPSA03311|The Binding of Isaac Repentance|USA|PS5
CHTM00777|PS4 Cheats Manager|HB|PS4

# PKGS: ContentID|Version|Type|TitleID|Title
UP9000-CUSA00900_00-BLOODBORNE000000|01.00|base|CUSA00900|Bloodborne™
UP9000-CUSA00900_00-BLOODBORNE000000|01.09|patch|CUSA00900|Bloodborne™
UP9000-CUSA00900_00-SPEXPANSIONDLC03|01.00|dlc|CUSA00900|Bloodborne The Old Hunters

Why keep a db?

Every run reads each PKG’s param.sfo anyway, so the db isn’t a speed-up. It’s there for things the PKGs alone can’t give you:

The db Without it
Remembers English names found online for Japanese/Korean titles Every run would repeat the online lookups: slower, rate-limited, and needs internet
Keeps your fixes: edit a game or DLC title and every run uses it (Using the db) No way to change a name without editing the script
Keeps game titles for folders with only DLC, or no PKGs DLC PKGs only contain the DLC’s own name, so the game title would be unknown
Gives one title per game, taken from the base game, for all its files Patch PKGs sometimes word the title differently
Holds the region used by --add-region  
Records every PKG you have, with content ID, version and type  

GAMES section

PKGS section

Using the db

The db is plain text, so you can open it in any text editor. After editing, do a dry run to check the new names, then --apply. The examples assume the script’s folder is ps4-pkg-title-renamer/ inside your games folder.

Rename a game. Edit its title in the GAMES section:

CUSA00900|Bloodborne™|USA|PS4         ->   CUSA00900|Bloodborne GOTY|USA|PS4

The game’s folder and all its PKGs follow, in whatever style you use: Bloodborne GOTY [CUSA00900]/Bloodborne GOTY [CUSA00900] [patch].pkg. DLC names follow too, keeping their DLC part: Bloodborne GOTY The Old Hunters [CUSA00900] [dlc].pkg. Use this to fix a lookup that missed an edition suffix, e.g. DoDonPachi DaiOuJou becomes DoDonPachi DaiOuJou Re-incarnation, or to shorten long titles.

Rename any PKG (base game, patch or DLC). Edit the last field, Title, of its PKGS line:

UP9000-CUSA00900_00-BLOODBORNE000000|01.04|base|CUSA00900|Bloodborne™
                               ->   ...|base|CUSA00900|Bloodborne™ Complete Edition
UP1004-CUSA23501_00-GTATHREE00000001|01.08|patch|CUSA23501|Grand Theft Auto III – The Definitive Edition
                               ->   ...|patch|CUSA23501|Grand Theft Auto III – The Definitive Edition Soundtrack Restoration Mod
UP9000-CUSA00900_00-SPEXPANSIONDLC03|01.00|dlc|CUSA00900|Bloodborne The Old Hunters
                               ->   ...|dlc|CUSA00900|The Old Hunters Expansion

On the next --apply:

Bloodborne Complete Edition [CUSA00900] [v1.04] [base].pkg
Grand Theft Auto III – The Definitive Edition Soundtrack Restoration Mod [CUSA23501] [v1.08] [patch].pkg
Bloodborne The Old Hunters Expansion [CUSA00900] [v1.00] [dlc].pkg

Change or fix a region tag (--add-region). Edit the Region field of the game. The recognised values are USA, EUR, JPN, ASIA, KOR and HB. Any other value is kept in the db but isn’t added as a tag.

Name a game the script can’t find. A folder or file with a title ID but no base game or patch PKG, e.g. only DLC, is reported as ID not in db. Add a GAMES line yourself and run again:

CUSA12345|My Game|USA

See what you have. The PKGS section lists every PKG, with its type and version:

grep '|patch|' ps4-pkg-title-renamer/ps4_titles.db             # every patch and its version
grep '|dlc|CUSA00900|' ps4-pkg-title-renamer/ps4_titles.db     # all DLC of one game
grep 'CUSA00900' ps4-pkg-title-renamer/ps4_titles.db           # everything for one game
Select-String '\|patch\|' ps4-pkg-title-renamer\ps4_titles.db  # Windows

A game with several patch lines has had more than one patch version on your drive. The db keeps a line for each version it has seen.

Open it in Excel. --export-xlsx writes the db as a spreadsheet you can sort and filter:

python3 ps4-pkg-title-renamer/ps4_rename.py --export-xlsx                  # -> ps4-pkg-title-renamer/ps4_titles.xlsx
python3 ps4-pkg-title-renamer/ps4_rename.py --export-xlsx my_games.xlsx    # or choose the file
Sheet Columns
Games Title ID, Title, Region, Base version, Latest patch, DLC (count)
PKGs Title ID, Game, Type, Version, Content ID, Title in db (the DLC name or your label)

Work offline. Once the db holds the English names, runs don’t need internet. --offline skips the online lookup for any new game.

Use the same names on another machine. Copy ps4_titles.db next to the script there. Your edited titles, DLC names and English names come along. It’s plain UTF-8 text, so it works on Linux, macOS and Windows.

Back up your edits. Git ignores the db, so copy ps4_titles.db somewhere safe before --build-db --rebuild. A rebuild starts from the PKGs again and discards every edit.

Updating the db

ps4_titles.db isn’t part of the repo and is listed in .gitignore. It’s created on the first run and grows as new games are found. Because git ignores it, it’s safe to keep next to the script in a clone, and git pull never conflicts with it.

English names for non-English titles

Some Asian releases only have a Japanese or Korean title. For those, --build-db searches English Wikipedia and then Wikidata, and only accepts results described as a video game:

CUSA10207: 배틀 가레가 Rev.2016      ->  Battle Garegga Rev.2016
CUSA32997: 怒首領蜂大往生 臨廻転生   ->  DoDonPachi DaiOuJou

Naming scheme

Every PS4 PKG is named from its own param.sfo, whatever it’s currently called. The PKG type is a tag like the others, [base], [patch] or [dlc]. In the default order, shown here, it’s the last tag:

<title>[ <ID>][ <region>][ <version>][ <content ID>] [base].pkg
<title>[ <ID>][ <region>][ <version>][ <content ID>] [patch].pkg
<title> <DLC title>[ <ID>][ <region>][ <version>][ <content ID>] [dlc].pkg
CATEGORY in param.sfo Type Default --add-id --no-title --add-id
gd, gde base game / app Bloodborne [base].pkg Bloodborne [CUSA00900] [base].pkg CUSA00900 [base].pkg
gp patch Bloodborne [patch].pkg Bloodborne [CUSA00900] [patch].pkg CUSA00900 [patch].pkg
ac DLC / add-on Bloodborne The Old Hunters [dlc].pkg Bloodborne The Old Hunters [CUSA00900] [dlc].pkg The Old Hunters [CUSA00900] [dlc].pkg
folder   Bloodborne/ Bloodborne [CUSA00900]/ Bloodborne [CUSA00900]/ (folders keep the title)

Name style options

These options can be combined freely:

Option Effect Applies to Example
--add-id adds the title ID after the title folders and files Bloodborne [CUSA00900] [patch].pkg
--no-title leaves the game title out, and writes the first part without brackets. Needs --add-id or --add-content-id .pkg files and game folders CUSA00900 [patch].pkg
--add-version adds a version tag before the type tag .pkg files Bloodborne [v1.09] [patch].pkg
--add-content-id adds a content ID tag before the type tag .pkg files Bloodborne [UP9000-CUSA00900_00-BLOODBORNE000000] [patch].pkg
--no-type leaves out the type tag .pkg files Bloodborne [v1.09].pkg
--add-region adds the region tag (from the db) after the title/ID folders and files Bloodborne [CUSA00900] [USA] [patch].pkg
--add-console adds the console tag (from the db) after the region folders and files Bloodborne [CUSA00900] [PS4] [patch].pkg
--sep SEP uses SEP instead of spaces, in titles and between tags folders and files --sep _: Grand_Theft_Auto_V_[CUSA00419]_[patch].pkg
--no-brackets writes tags without [ ] folders and files Bloodborne CUSA00900 v1.09 patch.pkg

Examples with several options:

--add-id --add-version --add-content-id
Bloodborne [CUSA00900]/
├── Bloodborne [CUSA00900] [v1.00] [UP9000-CUSA00900_00-BLOODBORNE000000] [base].pkg
├── Bloodborne [CUSA00900] [v1.09] [UP9000-CUSA00900_00-BLOODBORNE000000] [patch].pkg
└── Bloodborne The Old Hunters [CUSA00900] [v1.00] [UP9000-CUSA00900_00-SPEXPANSIONDLC03] [dlc].pkg

--add-id --add-version --sep _
Grand_Theft_Auto_V_[CUSA00419]/
└── Grand_Theft_Auto_V_[CUSA00419]_[v13.37]_[patch].pkg

--no-title --add-id --add-version
Bloodborne [CUSA00900]/
├── CUSA00900 [v1.04] [base].pkg
├── CUSA00900 [v1.09] [patch].pkg
└── The Old Hunters [CUSA00900] [v1.00] [dlc].pkg

--no-title --add-id --no-brackets --sep _
Bloodborne_CUSA00900/
├── CUSA00900_base.pkg
└── The_Old_Hunters_CUSA00900_dlc.pkg

--add-version --no-type
Bloodborne/
├── Bloodborne [v1.00].pkg
├── Bloodborne [v1.09].pkg
└── Bloodborne The Old Hunters [v1.00].pkg

File part order

--order sets the order of the parts in .pkg file names. Folders always keep title [ID] [region]. The parts are:

Part What it is Shown when
title the game title always, except with --no-title
label the DLC name, or a label from the db (see Using the db) DLC, and PKGs you’ve labelled
id [CUSA00900] --add-id
region [USA] --add-region
console [PS4] / [PS5] --add-console
version [v1.09] --add-version
cid [UP9000-CUSA00900_00-BLOODBORNE000000]. content-id also works as the name --add-content-id
type [base] / [patch] / [dlc] unless --no-type

The default order is title,label,id,region,console,version,cid,type. List the parts you want first. The rest follow in the default order:

--add-id --add-version                              Bloodborne [CUSA00900] [v1.09] [patch].pkg
--add-id --add-version --order id,title             [CUSA00900] Bloodborne [v1.09] [patch].pkg
--add-id --add-version --order type,version         [patch] [v1.09] Bloodborne [CUSA00900].pkg
--no-title --add-id --add-version --order version   v1.09 [CUSA00900] [patch].pkg
--add-id --add-region --no-brackets --sep _ --order region,id
                                                    USA_CUSA00900_Bloodborne_The_Old_Hunters_dlc.pkg

PS5 PKGs

PS5 .pkg files, e.g. fpkgs, are renamed like PS4 PKGs, with the same parts and options:

UP2103-PPSA03311_00-BOIREPENTANCEPS5.pkg  ->  The Binding of Isaac Repentance [PPSA03311] [PS5]/The Binding of Isaac Repentance [PPSA03311] [PS5] [v1.000.000] [base].pkg

Game folders (PS5 and dumped PS4 games)

Besides PKG files, the script renames extracted game folders: a PS5 game, or a dumped PS4 game, stored as a folder instead of a .pkg. It recognises them by their system file:

Folder contains Platform Read from it
sce_sys/param.json PS5 titleId, contentId, the English titleName under localizedParameters, and contentVersion
sce_sys/param.sfo PS4 dump the same fields as a PKG’s param.sfo. The version is VERSION, like a PS4 base game
The Binding of Isaac Repentance 01.000 PPSA03311/     ->  The Binding of Isaac Repentance [PPSA03311] [USA] [v1.000.000] [app]/
├── eboot.bin                                             ├── eboot.bin              (untouched)
├── PPSA03311.complete                                    ├── PPSA03311.complete     (untouched)
└── sce_sys/param.json                                    └── sce_sys/param.json     (untouched)

Loose PKGs in the top folder

A PKG directly in PATH, rather than in a game folder, is moved into its game’s folder:

Running again

Each run applies the naming options you give to everything, so re-running never renames anything twice:

Undo

Every --apply records each rename and move in rename_undo.log, in the script’s folder, so you can reverse them later. There are three ways to undo:

Command Reverts Acts
--undo Everything recorded under PATH, from every --apply run Immediately
--undo-last Only the most recent --apply run under PATH Preview. Add --apply to do it
--undo-match TEXT Only renames whose path contains TEXT Preview. Add --apply to do it

--undo-last and --undo-match can be combined, for example to undo only the matching renames from the last run. Undo always works newest first.

Examples

Run these from the games folder:

# revert everything
python3 ps4-pkg-title-renamer/ps4_rename.py --undo

# step back one --apply run at a time: preview, then do it
python3 ps4-pkg-title-renamer/ps4_rename.py --undo-last
python3 ps4-pkg-title-renamer/ps4_rename.py --undo-last --apply

# a single file
python3 ps4-pkg-title-renamer/ps4_rename.py --undo-match "Old Hunters" --apply

# one game: its folder and every file in it
python3 ps4-pkg-title-renamer/ps4_rename.py --undo-match Bloodborne --apply

# games in another folder: pass it as PATH
python3 ps4-pkg-title-renamer/ps4_rename.py ../other-games --undo-last --apply

A preview lists every rename it would revert as current name -> original name and changes nothing:

/games/Bloodborne/Bloodborne The Old Hunters [dlc].pkg -> /games/Bloodborne/Bloodborne The Old Hunters.pkg  (preview)

Preview only. Re-run with --apply to undo.

How --undo-match finds renames

What undo takes care of

The undo log

Logs

All logs are kept in the script’s folder, not in PATH. In a git clone, .gitignore excludes them. Every rename or undo run writes rename_results_<dryrun|apply|undo>_<timestamp>.log. Only the 5 newest are kept, and older ones are deleted automatically after each run. Use --keep-logs N to change the limit, or --keep-logs 0 to keep every log. rename_undo.log is never rotated.

=== CHANGED (143) ===
CUSA00900/CUSA00900_base.pkg  ->  Bloodborne [base].pkg
=== NOT CHANGED (39) ===
itemzflow/daemon.log  (no game ID in name)
Bloodborne [CUSA00900]/Bloodborne [CUSA00900] [base].pkg  (already named)
CUSA99999  (ID not in db: CUSA99999)
=== ERRORS (1) ===
CUSA00900/CUSA00900_patch.pkg  (target already exists: Bloodborne [patch].pkg)

--apply also records every rename in rename_undo.log, which the undo options use. See Undo.

To delete old results logs:

python3 ps4_rename.py --clean-logs

This deletes every rename_results_*.log in the script’s folder, plus any left in PATH by older versions. It never deletes rename_undo.log or rename_undo.log.done.

FAQ

How do I rename PS4 PKG files to their game names? Put the script in your PKG folder and run a dry run, then apply:

python3 ps4-pkg-title-renamer/ps4_rename.py            # preview
python3 ps4-pkg-title-renamer/ps4_rename.py --apply    # rename

See Quick start for more.

What is a CUSA number / PS4 title ID? Every PS4 game has a title ID such as CUSA00900, which is Bloodborne (USA). PKG dumps and downloads are often named only by that ID or by their content ID, e.g. UP9000-CUSA00900_00-BLOODBORNE000000. The script reads the ID and the real game title from the PKG’s param.sfo and renames the files for you.

How can I tell whether a PKG is the base game, a patch (update) or DLC? The script reads the CATEGORY field in param.sfo (gd = base game, gp = patch, ac = DLC/add-on) and tags the file [base], [patch] or [dlc]. Add --add-version to also see the version, e.g. [v1.09] for a patch.

Which version does --add-version show? For a patch, the version it updates the game to (APP_VER in param.sfo). For a base game, the version the base PKG was built at (VERSION), because a base PKG’s APP_VER is always 01.00. For example, Vice City’s base PKG is v1.07 and its patch is v1.08.

Does it work with fake PKGs (fPKG), GoldHEN and Itemzflow? It works with any PS4 PKG whose param.sfo can be read, which includes fake PKGs and homebrew. It only renames files and folders. It never changes the contents of a PKG, so the PKGs install the same way afterwards. Check whether your install tool expects the title ID in the name. If it does, use --add-id.

Can I keep the CUSA ID in the name? Yes, --add-id gives Bloodborne [CUSA00900] [base].pkg. Add --no-title to drop the game title from file names, e.g. CUSA00900 [base].pkg, and --add-region to add [USA].

Can I undo a rename? Yes. --undo reverts everything, --undo-last reverts the last run, and --undo-match TEXT reverts only matching names, e.g. one game or one file. See Undo.

Does it need an internet connection? Only to look up English names for Japanese/Korean/Chinese titles, and only once per game, because results are saved in the db. Use --offline to skip the lookup.

Does it work with PS5 games? Yes, with both kinds:

PS4 and PS5 versions of a game stay separate. Use --add-console to tag names [PS4] / [PS5].

Does it run on Windows? Yes, Windows 10/11, Linux and macOS, with Python 3.8+ and no other dependencies. See Installation.

Notes

License

Copyright (C) 2026 bsgonzalezq.

This project is free software under the GNU General Public License v3.0 or, at your option, any later version (GPL-3.0-or-later):