The command line
tessaridb-s3-cli: ls, cp, mv, rm, mb, rb, stat, presign and sync over the Rust client — with every deletion behind --yes and every change checked afterwards.
tessaridb-s3-cli does the work of the Rust client from a shell.
It is Apache-2.0, like the client.
Credentials
The endpoint and credentials come from the environment (TESSARIDB_S3_ENDPOINT,
TESSARIDB_S3_ACCESS_KEY, TESSARIDB_S3_SECRET_KEY, optionally
TESSARIDB_S3_REGION) or, when those are not set, from a profile file at
~/.config/tessaridb-s3/credentials, which must be readable by its owner alone
(chmod 600):
[default]
endpoint = https://s3.example.com
access_key = ...
secret_key = ...
--profile <name> picks another section. There is no flag for a secret: a
command-line argument is visible to every process on the machine and stays in shell
history.
Commands
tessaridb-s3-cli mb s3://photos
tessaridb-s3-cli cp holiday.jpg s3://photos/2026/
tessaridb-s3-cli ls s3://photos/ --recursive
tessaridb-s3-cli stat s3://photos/2026/holiday.jpg --json
tessaridb-s3-cli presign s3://photos/2026/holiday.jpg --expires 600
tessaridb-s3-cli sync ./albums s3://photos/albums
tessaridb-s3-cli rm s3://photos/2026 --recursive --yes
| command | what it does | changes data |
|---|---|---|
ls [s3://bucket[/prefix]] | the buckets, or one level of objects (--recursive: all of them) | no |
stat s3://bucket/key | size, ETag, CRC64NVME, last modified | no |
presign s3://bucket/key | a download link (--put: an upload link), --expires seconds (default 3600, at most 604800) | no |
mb s3://bucket | creates the bucket | yes |
cp SOURCE DEST | file → object, object → file, or object → object; an existing destination is replaced only with --yes | yes |
sync SOURCE DEST | a directory → a prefix, or back: copies what is missing or differs, never deletes | yes |
rb s3://bucket --yes | deletes an empty bucket | deletes |
rm s3://bucket/key --yes | deletes an object; --recursive everything under a prefix | deletes |
mv SOURCE DEST --yes | copies, checks the copy, then deletes the source | deletes |
Every command that changes data accepts --dry-run. A command that deletes refuses
to run without --yes. After each change the server (or the file system) is asked
again, and the command fails if the result is not what was asked.
sync decides a file is unchanged only when that is proven (equal size, then the MD5 a
single-part ETag carries, otherwise the CRC64NVME the server keeps) and sends it
otherwise. Going down, a key that would land outside the target directory is skipped,
reported, and makes the run fail.
Exit codes
| code | meaning |
|---|---|
| 0 | done |
| 2 | the command, a location or the settings are invalid; nothing was sent |
| 3 | a safety check refused: the destination exists, the bucket is not empty, the object is missing |
| 4 | the server or the file system failed |
| 5 | it ran, but the check afterwards found a different result |
| 130 | interrupted; an interrupted multipart upload stays open until it is aborted |