Skip to main content

hpcp

A simple script that can issue multiple cp -af commands simultaneously on a local system.

Optimized for use in HPC scenarios and featuring auto-tuning for files-per-process.

Includes an adaptive progress bar for copying tasks from multiCMD.

Tested on a Lustre filesystem with 1.5 PB capacity running on 180 HDDs. Compared to using tar, hpcp reduced the time for tarball/image release from over 8 hours to under 10 minutes.

Development status

Basic functionality (parallel copy) should be stable.

Imaging functionality (source/destination as .img files) includes differential patch images (-diff / -siff, see below). Imaging is only available on Linux—similar to tar, but uses disk images.

Block-image functionality is in beta. Only available on Linux. Possible use case: cloning a currently running OS without mounting / as read-only.

hpcp.bat available on github: simple old tk based GUI intended for basic windows functionality.

Important Implementation Detail

By default, hpcp only checks:

  1. The file’s relative path/name is identical.
  2. The file mtime is identical.
  3. The last -hs --hash_size bytes (defaults to 65536) are identical.

Although in most cases these checks should confirm that both files are identical, in certain scenarios (like bit rot), corrupted files might not be detected. If you need to verify file integrity rather than perform a quick sync, it is recommended to use the -fh --full_hash option.

Setting -hs --hash_size to 0 disables hash checks entirely. This can be helpful on HDDs, as they usually have suboptimal seek performance. However, HDDs are also more prone to bit rot. If the operator can accept that risk, it is possible to rely solely on mtime checks for file comparison by setting hash_size to 0. (Though on a single HDD, the standard cp command is already well-optimized.)

Installation

pipx install hpcp

or

pip install hpcp

After installation, hpcp is available as hpcp. You can check its version and libraries via:

hpcp -V

It is recommended to install via pip, but hpcp can also function as a single script using Python’s default libraries.

Note:

  • Using pip will optionally install the hashing library xxhash, which can reduce CPU usage for partial hashing and increase performance when using -fh --full_hash.
  • pip also installs multiCMD, used to issue commands and provide helper functions. If it is not available, hpcp.py will use its built-in multiCMD interface, which is more limited, has lower performance, and may have issues with files containing spaces. Please install multiCMD if possible.

Disk Imaging Feature Note

Only available on Linux currently!

-dd --disk_dump mode differs from the standard Linux dd program. hpcp will try to mount the block device/image file to a temporary directory and perform a file-based copy to an identically-created image file specified with -di --dest_image. This functionality is implemented crudely and is still an alpha feature. It works on basic partition types (it does not work with LVM) with GPT partition tables and has been proven able to clone live running system disks to disk images, which can then be booted without issues.
The created disk image can be resized using the -ddr --dd_resize option to the desired size. (This feature is provided so that you can shrink the raw size of the resulting image and provides some shrink capability for XFS.)
For partitions that hpcp cannot create a separate unique mount point, hpcp will fall back to using the Linux program dd to clone the drive. Note that this can be risky and can lead to broken filesystems if the drive is actively being written to. (However, since you generally cannot mount that partition on the current OS, the real-world scenarios for this remain limited.)

Filesystem parameter mirroring

In -dd mode hpcp reads each source filesystem's creation parameters and recreates the destination with matching geometry and features, instead of whatever the local mkfs defaults happen to be. Coverage varies by filesystem: ext2/3/4 (block size, inode size, inode ratio, reserved percentage, full feature set), xfs (block/sector/inode/directory geometry and v5 feature flags), btrfs (nodesize, sectorsize, checksum type, features), FAT (width, sector and cluster size, FAT count, reserved sectors), ntfs and exfat (cluster and sector size), f2fs (geometry and features), udf and reiserfs (block size and format), hfs+ (allocation block size), and minix (filesystem version and filename length).

Without it, a clone built on a modern host can be unmountable or unbootable on the system it came from — for example a FAT32 EFI System Partition recreated as FAT16, or an ext4 /boot that gains metadata_csum and 64bit that its bootloader does not understand.

Size-dependent values are scaled rather than copied, so -ddr resizes stay valid: the ext inode ratio and reserved percentage are mirrored, never absolute counts. If mkfs rejects a mirrored parameter set, hpcp warns and retries with defaults rather than failing the copy. Use -nfp to turn mirroring off entirely.

Patch Images Feature Note

Only available on Linux (loop devices and mounts, so usually root).

-diff [PATCH.img] compares a new tree (a directory, or a single-filesystem image with -si) against a base (-d DIR or -di IMG) and writes a patch image. The patch is an ordinary xfs/ext4 image, split with -dis like -di output. It holds every added or modified file whole at its real path, plus .hpcp_diff/manifest and .hpcp_diff/changes.tsv, which list every added, modified and deleted path with its before and after state. A moved file appears as one delete plus one add. A file counts as modified when its content, size, mtime, mode, owner, ACLs, file capabilities or user xattrs change; a directory when its mode, owner, ACLs or user xattrs change; a symlink when its target changes. Other xattrs (such as trusted.*, security.selinux or filesystem-internal ones) are ignored. Without a value the patch is named DIFF_<src>_TO_<base>_<time>.img.

A -di image store keeps files at their absolute source path. When the base is such a store, a directory is compared only with its own subtree inside the store, and the patch uses the same layout. So hpcp -siff patch.img -di store.img updates the store in place, and hpcp -siff patch.img -d / updates the live system.

-siff PATCH.img applies a patch to -d DIR, -di IMG or a single path. Repeat it for every -dis volume. It first checks every path the patch touches. If the target differs from what the patch expects, it lists the conflicts and asks Apply anyway? [y/N]; the default, and any non-interactive run, aborts. -fa --force_apply applies anyway and prints each conflict as a warning. Re-running a patch is safe because already-updated paths are skipped, and every touched path is verified afterwards.

Files and symlinks are replaced atomically: the new version is written next to the old one and renamed over it, so running processes keep the old file and an interrupted apply leaves each file either old or new. A directory the patch deletes is removed only if it is empty once the patch's own deletions are done; whole trees are removed only for conflicts forced with -fa. Paths are followed through symlinked directories that stay inside the target; if any path the patch deletes or writes resolves outside the target through a symlink, nothing is applied, even with -fa.

An apply that is killed partway leaves directories it created private (mode 0700, owned by root) until the final metadata pass runs. Re-running the same patch then reports those directories as conflicts; re-run with -fa to finish.

changes.tsv is also what -dfl writes:

#hpcp-changes	1
#op	path	old	new
D	gone.txt	f:<size>:<mtime_ns>:<mode>:<uid>:<gid>:<hash>:<xattr>	-
A	newdir/	-	d:<mode>:<uid>:<gid>:<xattr>
M	link	l:old-target	l:new-target

Paths escape \, tab, newline and carriage return as \\, \t, \n, \r.

Limitations:

  • Hard links are not preserved; applying a patch breaks them.
  • Special files (FIFOs, sockets, devices) are ignored.
  • Even a small patch is an image of roughly 50 MiB.
  • Generating and applying a patch need root (loop devices, mkfs, mount).
  • Nothing else may modify the target while a patch is applied.

Remove Extra Feature Note

-rme --remove_extra: Especially when combined with -rf, PLEASE PAY CLOSE ATTENTION TO YOUR TARGET DIRECTORY!
--remove_extra will remove all files that are not in the source path. When you are copying a file into a folder, you almost certainly do not want to use this!

Remove Feature Note

-rm --remove can remove files in bulk. This might be helpful on distributed file systems like Lustre, as it only gathers the file list once and performs bulk deletion rather than the default recursive deletion in the Linux rm program.

-rf --remove_force implies --remove. Use with care! This skips the interactive check requiring user confirmation before removing. If hpcp did not generate the correct file list from the specified source paths, hopefully you have fast enough reflexes to press Ctrl + C repeatedly to stop all parallel deletion processes if you realize a mistake.

-b --batch: Using -b with -rm will gather the file list for all source_paths first, then issue the remove command. This can be helpful because hpcp will tune its -f --files_per_job parameter accordingly for each task, and running one large remove job might be faster than running many small ones. This is especially useful when working with glob patterns like *.

$ hpcp -h
usage: hpcp.py [-h] [-s] [-j MAX_WORKERS] [-b | -nb] [-v] [-do] [-nds] [-fh]
               [-hs HASH_SIZE] [-fpj FILES_PER_JOB] [-sfl SOURCE_FILE_LIST]
               [-fl TARGET_FILE_LIST] [-cfl] [-dfl [DIFF_FILE_LIST]] [-tdfl]
               [-nhfl] [-rm] [-rf] [-rme] [-rwloff] [-e EXCLUDE]
               [-x EXCLUDE_FILE] [-nlt] [-V] [-pfl] [-si SRC_IMAGE]
               [-siff LOAD_DIFF_IMAGE] [-d DEST_PATH] [-rds] [-di DEST_IMAGE]
               [-dis DEST_IMAGE_SIZE] [-diff [GET_DIFF_IMAGE]] [-fa] [-dd]
               [-ddr DD_RESIZE] [-nfp] [-L RATE_LIMIT] [-F FILE_RATE_LIMIT]
               [-tfs TARGET_FILE_SYSTEM] [-ncd] [-co]
               [-ctl COMMAND_TIMEOUT_LIMIT] [-enes]
               [src_path ...]

Copy files from source to destination

positional arguments:
  src_path              Source Path

options:
  -h, --help            show this help message and exit
  -s, --single_thread   Use serial processing
  -j, -m, -t, --max_workers MAX_WORKERS
                        Max workers for parallel processing. Default is 1 *
                        CPU count. Use negative numbers to indicate {n} * CPU
                        count, 0 means 1/2 CPU count.
  -b, --batch           Batch mode, process all files in one go
  -nb, --no_batch, --sequential
                        Do not use batch mode
  -v, --verbose         Verbose output
  -do, --directory_only
                        Only copy directory structure
  -nds, --no_directory_sync
                        Do not sync directory metadata, useful for verfication
  -fh, --full_hash      Checks the full hash of files
  -hs, --hash_size HASH_SIZE
                        Hash size in bytes, default is 65536. This means hpcp
                        will only check the last 64 KiB (about 1 page in a
                        SSD) of the file.
  -fpj, --files_per_job FILES_PER_JOB
                        Base number of files per job, will be adjusted
                        dynamically. Default is 1
  -sfl, -lfl, --source_file_list SOURCE_FILE_LIST
                        Load source file list from file, or use "-" to read
                        from stdin. Will treat it raw meaning do not expand
                        files / folders. files are seperated using newline. If
                        --compare_file_list is specified, it will be used as
                        source for compare
  -fl, -tfl, --target_file_list TARGET_FILE_LIST
                        Specify the file_list file to store list of files in
                        src_path to. If --compare_file_list is specified, it
                        will be used as targets for compare
  -cfl, --compare_file_list
                        Only compare file list. Use --file_list to specify a
                        existing file list or specify the dest_path to compare
                        src_path with. When not using with file_list, will
                        compare hash.
  -dfl, --diff_file_list [DIFF_FILE_LIST]
                        Implies --compare_file_list, specify a file name to
                        store the diff file list to or omit the value to auto-
                        determine.
  -tdfl, --tar_diff_file_list
                        Generate a tar compatible diff file list. ( update /
                        new files only )
  -nhfl, --no_hash_file_list
                        Do not append hash to file list
  -rm, --remove         Remove all files and folders specified in src_path
  -rf, --remove_force   Remove all files without prompt
  -rme, --remove_extra  Remove all files and folders in dest_path that are not
                        in src_path
  -rwloff, --do_not_remove_files_while_listing
                        Do not remove files while listing. This is useful if
                        you want to remove files after listing.
  -e, --exclude EXCLUDE
                        Exclude source files matching the pattern
  -x, --exclude_file EXCLUDE_FILE
                        Exclude source files matching the pattern in the file
  -nlt, --no_link_tracking
                        Do not copy files that symlinks point to.
  -V, --version         show program's version number and exit
  -pfl, --parallel_file_listing
                        Use parallel processing for file listing
  -si, --src_image SRC_IMAGE
                        Source Image, mount the image and copy the files from
                        it.
  -siff, --load_diff_image LOAD_DIFF_IMAGE
                        Apply a patch image made by -diff to the target (-d /
                        -di or a single path). Repeat for each -dis volume.
                        Every path the patch touches is checked first;
                        conflicts prompt before being overridden.
  -d, -C, --dest_path DEST_PATH
                        Destination Path
  -rds, --random_dest_selection
                        Randomly select destination path from the list of
                        destination paths instead of filling round robin. Can
                        speed up transfer if dests are on different devices.
                        Warning: can cause unable to fit in big files as dests
                        are filled up by smaller files.
  -di, --dest_image DEST_IMAGE
                        Base name for destination Image, create a image file
                        and copy the files into it.
  -dis, --dest_image_size DEST_IMAGE_SIZE
                        Destination Image Size, specify the size of the
                        destination image to split into. Default is 0 (No
                        split). Example: {10TiB} or {1G}
  -diff, --get_diff_image [GET_DIFF_IMAGE]
                        Generate a patch image that updates the base (-d /
                        -di) to the source (src_path / -si): added and
                        modified files in full plus a change list under
                        .hpcp_diff/. Optionally name the output; default
                        DIFF_<src>_TO_<base>_<time>.img. Honors -dis, -fh, -hs
                        and -e.
  -fa, --force_apply    With -siff, apply even when the target differs from
                        the state the patch expects. Conflicts are still
                        printed as warnings.
  -dd, --disk_dump      Disk to Disk mirror, use this if you are backuping /
                        deploying an OS from / to a disk. Require 1 source,
                        can be 1 src_path or 1 -si src_image, require 1 -di
                        dest_image. Note: will only actually use dd if unable
                        to mount / create a partition.
  -ddr, --dd_resize DD_RESIZE
                        Resize the destination image to the specified size
                        with -dd. Applies to biggest partiton first. Specify
                        multiple -ddr to resize subsequent sized partitions.
                        Example: {100GiB} or {200G}
  -nfp, --no_fs_param_mirror
                        Do not mirror source filesystem parameters (geometry,
                        features) in -dd mode. Create destination filesystems
                        with mkfs defaults, preserving only label and UUID.
  -L, -rl, --rate_limit RATE_LIMIT
                        Approximate a rate limit the copy speed in
                        bytes/second. Example: 10M for 10 MB/s, 1Gi for 1
                        GiB/s. Default is 0: no rate limit.
  -F, -frl, --file_rate_limit FILE_RATE_LIMIT
                        Approximate a rate limit the copy speed in
                        files/second. Example: 10K for 10000 files/s, 1Ki for
                        1024 files/s. Default is 0: no rate limit.
  -tfs, --target_file_system TARGET_FILE_SYSTEM
                        Specify the target file system type. Will abort if the
                        target file system type does not match. Example: ext4,
                        xfs, f2fs, ntfs, fat32, exfat. Default is None: do not
                        check target file system type.
  -ncd, --no_create_dir
                        Ignore any destination folder that does not already
                        exist. ( Will still copy if dest is a file )
  -co, --content_only   Content-only copy: do not sync mode, owner, or
                        timestamps on files or directories. Still create
                        missing destination directories using filesystem-
                        default permissions (so parent ACL/setgid/setuid
                        inherit).
  -ctl, --command_timeout_limit COMMAND_TIMEOUT_LIMIT
                        Set the command timeout limit in seconds for external
                        commands ( ex. cp / dd ). Default is 0: no timeout.
  -enes, --exit_not_enough_space
                        Exit if there is not enough space on the destination
                        instead of continuing (Note: Default is continue as in
                        compressed fs copy can be down even if source is
                        bigger than free space).

Metadata

Release files for hpcp 9.66

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hpcp 9.66
File Size Uploaded Provenance
hpcp-9.66.tar.gz 142.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for hpcp 9.66
File Interpreter ABI Platform
hpcp-9.66-py3-none-any.whl Python 3 none any Details

Total release size: 236.7 kB

Release files / hpcp-9.66.tar.gz

Download URL hpcp-9.66.tar.gz
Size 142.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a989f555e2cba2bb9516678597baa33588dc74ab0bcadd2502721df418f88f19
BLAKE2b-256 checksum
How to use checksums
27e4aaccb4fe55a3c1ab2c8655a113bef96f778c84ec98793f98e9e9dbb7b248
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / hpcp-9.66-py3-none-any.whl

Download URL hpcp-9.66-py3-none-any.whl
Size 93.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d6ccfc351f7bedb7f71f6786f283b96f9095509c4744d47d9a4d648ec7392ad8
BLAKE2b-256 checksum
How to use checksums
5b429bf07e2391ee93015dac0c3f925bac87d1a8b2a494e050a5ce7f9dc6f52a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for hpcp 9.66

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

9.66 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page