Name the database each command uses on stderr (closes #111)
check / check (push) Canceled after 0s

scan, report and trees now print one line on stderr before anything
else, naming the database and whether its path is the default or comes
from SFDUPES_DATABASE; scan also says when the file is new. report and
trees print it before opening the database, so a missing-database error
follows it. A relative path gets the working directory put in front of
it, with its symlinks resolved as the kernel reports it, and is not
cleaned: a ".." after a symlink names another file than the cleaned
path does. README "Database" lists when scan writes each file.

Unverified: the line on a terminal has no test of its own.

Model: opus-5-5
This commit was merged in pull request #118.
This commit is contained in:
2026-10-16 15:28:02 +02:00
parent 198cefa152
commit 264817c413
9 changed files with 412 additions and 36 deletions
+39 -4
View File
@@ -96,10 +96,11 @@ As a file `/etc/cron.d/sfdupes`:
the first scan. To keep it elsewhere, set
`SFDUPES_DATABASE=/path/to/db.sqlite` before the command on the same line.
- `scan` writes nothing to stdout. Its stderr, appended here to
`/var/log/sfdupes.log`, holds a plain progress line as each phase starts and
then at most every 5 seconds, a warning for each path it skips, and the
summary line (see "Progress" and "`scan` mode"). The log grows with every
scan; rotate it like any other.
`/var/log/sfdupes.log`, holds a first line naming the database (see
"Database"), a plain progress line as each phase starts and then at most every
5 seconds, a warning for each path it skips, and the summary line (see
"Progress" and "`scan` mode"). The log grows with every scan; rotate it like
any other.
- Skipped paths do not fail a scan: it still exits 0, and cron sends nothing. A
scan that fails, or is stopped by `SIGINT` or `SIGTERM`, exits 1 with the
reason among the last lines of the log; `tail` prints them, and cron mails
@@ -266,6 +267,26 @@ All three subcommands operate on a single SQLite database file:
command-line flag. The path names the file exactly, whatever characters it
holds (`?`, `#` and `%` included); a relative path is relative to the working
directory.
- Each subcommand first prints one line on stderr naming the database it uses,
before anything else it prints (progress displays included), whether or not
stderr is a terminal. The line gives the path with the working directory put
in front of it when it is relative, and otherwise as set (a `..` in it stays,
so the line names the same file), escaped like the paths in a report (see
"Report output format"), and says where the path came from:
```
scan: new database /var/lib/sfdupes/db.sqlite (default)
trees: database /srv/tmp/sfdupes/db.db (from SFDUPES_DATABASE)
```
The working directory put in front is the one `pwd -P` prints, with its
symlinks resolved. After a `cd` through a symlink to a directory, a path
starting `../` therefore names a file beside the directory the symlink leads
to, as it does for any other program. `scan` says `new database` when no
file is at that path as it starts. `report` and `trees` print the line
before they open the database, so the error for a missing database comes
after it.
- `scan` creates the database (and its parent directory) on first use. `report`
and `trees` require an existing database; a missing database file is a fatal
error (exit 1) telling the user to run `scan` first.
@@ -304,6 +325,20 @@ All three subcommands operate on a single SQLite database file:
in WAL mode until the next scan. `report` writes each row as it reads it, so
it is still reading while its output is paused (a pager, a stalled pipe), and
a `scan` started then fails after the busy timeout.
- A `scan` writes to the database and the files beside it at these points (its
phases are described under "`scan` mode"):
- As it starts, before the walk: the directory, an empty database file and
the `.lock` file, each only if missing.
- Then, still before the walk: the schema, in a new database, and the `-wal`
and `-shm` files, which stay beside the database while the scan runs.
- While it loads the existing records (`load`) and walks: no records. A
first scan's database holds none, however long its walk has run.
- During the hash phase: the first records, committed 10,000 at a time.
- In the update phase: the rest of the hashed records, the records for
size-unique files, and the deletions.
- In the content phase: content hashes, again committed 10,000 at a time.
- At the end, as it closes the database: the `-wal` and `-shm` files go
away, unless a report still has the database open (see above).
- `report` and `trees` open the database read-only and need only read access to
the database file, and no write access to its directory. While the database is
in WAL mode they also read the `-wal` and `-shm` files beside it, which SQLite