delete files

Brian K. White brian at
Tue Nov 15 15:49:04 MST 2011

On 11/15/2011 4:15 AM, Voelker, Bernhard wrote:
> Brian K. White wrote:
>> On 11/14/2011 2:29 AM, Voelker, Bernhard wrote:
>>> rsync -avx --delete --include=/file --exclude='*' . host2:deltest/.
>> This didn't work for me, although one difference is my script specifies
>> a path instead of "." Does this only work with literally "." in the
>> places above?
>> ...
>> For the new delete mode it detects if the supplied argument doesn't
>> exist locally and does this instead:
>> P=/path/to/some
>> F=thing
>> h=target_host
>> OPTS="-acv --delete"
>> rsync $OPTS --include=/$F --exclude='*' $P ${h}::root$P
>> Which to me looks the same as what you did except that I'm using an
>> explicit full path with leading "/" in $P instead of "."
>> But when it runs the remote file is not deleted.
>> After creating /tmp/floof/{1,2,3} locally and pushing that all out to a
>> remote box, then deleting /tmp/floof/2 locally, then trying to push out
>> the non-existing /tmp/floof/2 to the same remote host, I just get:
>> ----------
>> sending incremental file list
>> rsync: link_stat "/tmp/floof/2" failed: No such file or directory (2)
>> sent 12 bytes  received 12 bytes  48.00 bytes/sec
>> total size is 0  speedup is 0.00
>> rsync error: some files/attrs were not transferred (see previous errors)
>> (code 23) at main.c(1042) [sender=3.0.7]
>> ----------
> I've never seen this.
> Personally spoken, I've ever been always confused about the use of $P
> (a directory name) together with include or exclude rules, so I turned
> to appending "/." to the source and the destination argument:
> 	rsync -avx [other options] somedir/.  user at server:[/]some/dir/.
> in your case:
> 	rsync $OPTS --include=/$F --exclude='*' "$P/." "${h}::root$P/."
> Do you have an older rsync on one of the peer sides?
> Have a nice day,
> Berny

All are 3.0.7
I can relatively easily up them all to current stable too, just haven't 
gotten to it yet.

Interesting about just adding /. to everything that is meant to refer to 
a directory. Seems like something must be wrong by definition, if you 
have to apply such a simple static rule exactly the same way everywhere, 
then really you shouldn't have to apply it anywhere. I will have to test 
that very carefully because this script handles a lot of different 

... Looks like it works, but only for files not directories.

All I did was change:
rsync $OPTS --include=/$F --exclude='*' $P ${h}::root$P
rsync $OPTS --include=/$F --exclude='*' ${P}/. ${h}::root${P}/.

And now if the file doesn't exist locally it is deleted from the remote 

I still get a does not exist message from the local rsync, but the file 
is deleted from the remote machine.

I reverted that change and tested again and definitely without the /. 
and no other change, the file is not deleted from the remote side.

Everyone at my company has been using the script for years now to push 
out all manner of files and directories, trees, and even shell expansion 
patterns where $F is really file.{prc,tok} and it's been solid so 
definitely the extra /. is not needed for normal syncing.

Now, next I will have to see if I need to handle that F=file.{prc,tok} 
case specially in the delete case, maybe I need to detect it and write a 
multiline include-from file or expand it into multiple --include options.

And It's not handling rm -rf of a whole directory yet but I think that's 
going to just be some normal trial & error to detect and adjust for some 
different conditions. If the user specifies a target with a trailing 
"/", handle that differently. How I don't know yet but you got me past 
the main problem already, deleting specific files does work. And I 
already know that if I rm -rf /tmp/dir and then "rsync -av --del /tmp 
host::root" it absolutely will delete /tmp/dir on the remote host, so 
it's got to just be a matter of adjusting the path/file arguments in the 
include/exclude and on the command line differently for a directory than 
for a file, and I'm OK with requiring the user to supply the trailing 
"/" to indicate a directory. (I suppose I could pull a listing from the 
remote host to determine that automatically as an optional enhancement 

So far everything I try just results in:
nj2:/opt/x # rsync -avvvn --force --delete --include=/tmp 
--include=floof/ --exclude='*' /tmp/. co4::root/tmp/.
[client] add_rule(+ /tmp)
[client] add_rule(+ floof/)
[client] add_rule(- *)
opening tcp connection to co4 port 873
sending daemon args: --server -vvvnlogDtpre.isf --delete --force . 
sending incremental file list
[sender] make_file(.,*,0)
[sender] hiding directory cgi because of pattern *
[sender] hiding directory brw because of pattern *
[sender] hiding directory dat because of pattern *
[sender] hiding file fpwp2.7108 because of pattern *
[sender] hiding file fpwp2.8444 because of pattern *
[sender] hiding file fpwp2.8777 because of pattern *
send_file_list done
send_files starting
send_files(0, /tmp/.)
cannot delete non-empty directory: floof
send_files phase=1
send_files phase=2
send files finished
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 68 bytes  received 11 bytes  52.67 bytes/sec
total size is 0  speedup is 0.00 (DRY RUN)
[sender] _exit_cleanup(code=0, file=main.c, line=1042): about to call 

Every single line in "..." says "hiding" because the directory doesn't 
exist locally.

I've tried other combinations than above but not every possible 
combination I can think of yet.


More information about the rsync mailing list