Looking at âman nextcloudcmdâ it says âA sync run synchronizes a single local directory using a WebDAV share on a remote nextCloud serverâ
So, if a file is existing on the server but missing on the client: will it be deleted on the server or will this file be copied from the server to the client?
And, if a file is existing on the client but missing on the server: will it be deleted on the client or will this file be copied from the client to the server?
Iâm runnung nextcloudcmd on a linux system, but this might not be relevant (?).
Quick note on what nextcloudcmd actually is: itâs the same sync engine as the regular desktop client, just without the GUI â it runs headless, does a single sync pass, and exits. The desktop client runs permanently in the background and reacts to file changes; nextcloudcmd does the same thing once on demand, which makes it suitable for scripts and cron jobs. The official documentation is here. Because the underlying engine is identical, everything below applies to both.
The answer to your question depends entirely on one thing: the sync journal.
nextcloudcmd keeps a small SQLite database file called .sync_*.db in your local sync directory. This journal records every file that has ever been successfully synced between client and server. It is the only way the program can tell the difference between âthis file is newâ and âthis file was deletedâ.
Scenario A â File exists on the server, your local folder doesnât have it
The program looks up the file in the journal:
Not in the journal (never synced before): âI have no record of this file â it must be new on the server.â â downloaded to the client.
// Unknown in db: new file on the server
Q_ASSERT(!dbEntry.isValid());
...
item->_instruction = CSYNC_INSTRUCTION_NEW;
item->_direction = SyncFileItem::Down;
In the journal (was synced before, now missing locally): âI know this file â it existed on the client before and is now gone. It was deleted locally.â â deletion is propagated to the server.
// Removed locally: also remove on the server.
item->_instruction = CSYNC_INSTRUCTION_REMOVE;
item->_direction = SyncFileItem::Up;
Scenario B â File exists on your local folder, server doesnât have it
Same logic in reverse: if the file is not in the journal, it is treated as new and uploaded. If it was in the journal (meaning the server previously had it and it disappeared), the deletion is propagated to the client.
Practical summary
Situation
Journal entry?
Result
File on server, not on client
No
Downloaded to client
File on server, not on client
Yes
Client deletion propagated â deleted from server
File on client, not on server
No
Uploaded to server
File on client, not on server
Yes
Server deletion propagated â deleted from client
First run (no journal exists yet): every file on both sides is treated as new and synced bidirectionally. Nothing is deleted.
Caution: if the journal exists from a previous sync but your local folder is now empty (e.g. you moved the files elsewhere), nextcloudcmd will interpret every file as âdeleted locallyâ and delete them from the server too.
Inspecting the journal yourself
The journal is a standard SQLite database. If you want to check whether a file is tracked before running nextcloudcmd, you can read it directly (install sqlite3 if needed: apt install sqlite3).
Find the journal in your local sync folder:
ls -la /path/to/your/syncfolder/.sync_*.db
List all files currently tracked in the journal:
sqlite3 /path/to/your/syncfolder/.sync_*.db "SELECT path, modtime, filesize FROM metadata;"
Check whether a specific file is tracked:
sqlite3 /path/to/your/syncfolder/.sync_*.db "SELECT path FROM metadata WHERE path LIKE '%yourfilename%';"
If the query returns a row, the file is known to the sync engine â a missing copy on either side will be treated as a deletion. If it returns nothing, it is treated as new and will be synced over.
The three files always belong together
You may notice that the journal is not a single file but three:
.sync_3eea21c084cb.db â main database
.sync_3eea21c084cb.db-shm â Shared Memory index (32 KB, fixed size)
.sync_3eea21c084cb.db-wal â Write-Ahead Log
SQLite operates in WAL mode (Write-Ahead Log). Instead of writing changes directly into the main .db file, SQLite appends every write to the .db-wal file first â this is faster and safer because it avoids modifying the main database mid-write. The .db-shm file is a shared-memory index that helps multiple readers locate the right entries in the WAL without locking each other out.
These three files form a single logical database. Never copy or back up just the .db without the other two â you would get a database that is missing all changes written since the last checkpoint. Always copy all three together.
The WAL is periodically folded back into the main database in an operation called a checkpoint. SQLite triggers this automatically when the WAL reaches around 1000 pages (~4 MB). Until then, the WAL grows with every sync run. This is why the WAL file can be noticeably larger than the main database â even when the client reports everything as synced and is sitting idle. It does not indicate any problem: SQLite simply hasnât hit the checkpoint threshold yet, or the last checkpoint left some pages behind for reader-safety reasons. The correct database state is always .db + .db-wal read together.
The touch approach is a perfectly valid practical test â create an empty file on each side, run nextcloudcmd, observe what happens, and since the files are empty you lose nothing. Highly recommended to verify behaviour on your specific setup. What the code analysis above adds is the why: knowing about the journal means you can predict the outcome in advance rather than having to test every scenario, and it explains why the same operation behaves differently depending on whether a previous sync has run or not.
I went through the sync engine source code to write this up â itâs been a long time since I last read C++ seriously, so I may have missed something. But the core logic around the journal should be correct.