isf
isf (interactive shared folder) keeps a local folder and a remote one the same, both ways, over ssh. Change a file on either side and it shows up on the other a moment later.
$ isf ./proj server:proj isf: ./proj ⇄ server:proj ↑ src/main.c ↓ notes.md isf: in sync: 1 sent, 1 received isf: watching for changes, Ctrl-C to stop ↑ src/main.c ↓ todo deleted
Requirements
- Linux on both machines (isf uses inotify to see changes).
- ssh access to the remote, with SFTP enabled (the OpenSSH default).
- The same isf on both machines: the local one starts a copy on the remote and stops if it isn't the same version.
curlorwget, only forisf --update.
Installation
The releases have isf for x86_64
and aarch64, as a static binary and as an AppImage. nightly
is built from every push to main.
$ curl -Lo ~/.local/bin/isf https://github.com/hugoocoto/isf/releases/download/nightly/isf-x86_64 $ chmod +x ~/.local/bin/isf
Or build it:
$ git clone --recurse-submodules https://github.com/hugoocoto/isf $ cd isf $ make && cp isf ~/.local/bin/
Then put the same binary on the remote, for example with
scp isf server:.local/bin/isf. If it isn't in the
PATH of commands run over ssh, tell isf once and it
remembers:
$ isf ./proj server:proj -I .local/bin/isf
It is also available through the pm
user repository. isf --update replaces isf with the
newest release; run it on both machines.
Usage
isf [folder...] [[user@]host:folder] [options]
The first time, give the local folder and where it goes, like
scp:
$ isf ./proj server:proj # ./proj with ~/proj on server $ isf ./proj server:/srv/proj # an absolute path on the remote $ isf ./proj me@server:proj -p 2222 # another user and port $ isf a b server:backups/ # backups/a and backups/b
A remote folder ending in / means "inside it". After the
first run isf remembers where each folder syncs to, so
isf ./proj, or just isf inside the folder, is
enough. It runs until Ctrl-C; with --once it syncs what is
different now and exits, for scripts and cron jobs.
Options
| Option | Description |
|---|---|
-p, --port PORT |
ssh port |
-I, --isf PATH |
where isf is on the remote |
-j, --jobs N |
transfer up to N files at once (default 4) |
-n, --dry-run |
show what syncing would do and exit |
--once |
sync what is different now and exit |
-q, --quiet |
don't list each file |
-v, --verbose |
show every file system event |
--reset |
forget previous syncs: sync like the first time |
--check-update, --update |
check for, or install, a newer release |
Output
↑ path sent to the remote (↓: received from it) ↑ path deleted removed there because it was removed here ↑ path mode only the permissions changed ↑ old → new renamed on both sides ! path changed on both sides: kept the newest, the other one is path.isf-conflict
How changes are decided
- If something changed on one side only, that side wins.
- If it changed on both, the newest modification time wins, and the
other version is kept as
FILE.isf-conflicton both sides. - If one side deleted it and the other edited it, the edit wins.
- A file kept open while it's written (a log) is synced once the writes stop for a couple of seconds.
isf syncs files, folders and symlinks (as symlinks) with their permissions and modification times. It does not sync owners, groups or hard links.
Ignoring files
Put patterns in a .isfignore file at the top of the
synced folder, with .gitignore-like syntax:
# any name that matches, in any directory *.log # a trailing / matches only directories build/ # a leading / is relative to the folder /secret.txt
Editor temp files (*.swp, *~,
4913, .#*) are always ignored.
.isfignore is synced too, so both sides use the same
patterns.
Safety
- Files are written next to their place and renamed in, so a half-written file is never seen.
- If a previously synced folder is empty on one side at start, isf stops instead of deleting everything on the other side.
- If the connection drops, isf reconnects and syncs what changed meanwhile.
Limitations
- A remote edit made while isf wasn't running, that kept the size and landed in the same second as the last sync, can be missed.
- On network filesystems (NFS, Lustre, SMB) changes made by other machines raise no events; isf polls them every 5 seconds.
- Linux limits inotify watches per user; very large trees can run out. isf tells you how to raise the limit.
- IPv6 addresses need a host alias in
~/.ssh/config.
See also
- Tools and applications