Provedl jsem pouze omezené testování funkčnosti, takže buďte opatrní s tímto příkazem (--dry-run):
rsync -avPr --ignore-existing --remove-source-files src/ dest
Všimněte si prosím koncové /, protože se vrátí do src namísto zkopírování samotného src, mělo by to zachovat vaše stávající cesty.
Použitím příznaku --ignore-existing v kombinaci s příznakem --remove-source-files odstraníte pouze soubory ze zdroje src, které jsou synchronizovány ze zdroje src do cíle, tedy soubory, které dříve neexistovaly pouze v cíli.
Pro smazání nesynchronizovaných souborů, tedy těch, které již existovaly v dest/ jako v src/, můžete použít:
for file in `find src/ -type f`; do diff $file `echo $file | sed 's/src/dest/'` && rm $file || echo $file; done
nebo
find src -type f -exec bash -c 'cmp -s "$0" "${0/#src/dest}" && rm "$0"' {} \;
pokud by názvy souborů mohly obsahovat mezery/nové řádky/…Co se týká Gillesova komentáře týkajícího se speciálních znaků, na to je určitě třeba pamatovat a existuje mnoho řešení, nejjednodušší by bylo předat -i do rm, které se zobrazí před smazáním. Za předpokladu, že je k nalezení poskytnut src/ nebo jeho nadřazená cesta, měla by plně kvalifikovaná cesta vést k tomu, že všechny názvy souborů budou správně zpracovány jak příkazy diff, tak rm bez uvozovek.
jednohlasné je nástroj, který hledáte. Pokud dáváte přednost gui, zkuste unison-gtk. Ale nemyslím si, že to smaže podobné soubory:unisono zkuste mít oba adresáře identické. Nicméně snadno 1) určí, které soubory se mají kopírovat; 2) které potřebují ruční sloučení.
Následující skript by měl dělat věci rozumně. Přesouvá soubory ze zdroje do cíle, nikdy nepřepisuje soubor a vytváří adresáře podle potřeby. Zdrojové soubory, které mají v cíli odpovídající jiný soubor, jsou ponechány samotné, stejně jako soubory, které nejsou běžnými soubory nebo adresáři (např. symbolické odkazy). Soubory zbylé ve zdroji jsou ty, u kterých došlo ke konfliktu. Pozor, vůbec jsem to netestoval.
cd src
find . -exec sh -c '
set -- "/path/to/dest/$0"
if [ -d "$0" ]; then # the source is a directory
if ! [ -e "$1" ]; then
mv -- "$0" "$1" # move whole directory in one go
fi
elif ! [ -e "$0" ]; then # the source doesn't exist after all
: # might happen if a whole directory was moved
elif ! [ -e "$1" ]; then # the destination doesn't exist
mv -- "$0" "$1"
elif [ -f "$1" ] && cmp -s -- "$0" "$1"; then # identical files
rm -- "$0"
fi
' {} \;
Dalším přístupem by bylo provést sjednocené připojení jednoho adresáře nad druhým, například pomocí funionfs nebo unionfs-fuse.