You can do this with a single
RewriteRule. The trick here is to only check for valid username characters, not everything (ie.
.* - I wouldn't have thought your usernames could literally be anything?). This would also be more efficient since not every request will match and be processed.
For example, assuming your usernames can only consist of upper/lowercase letters and numbers then:
RewriteRule ^([a-zA-Z0-9])$ /remote.php/carddav/addressbooks/$1/contacts [R=301]
This is very similar to your initial attempt. Note that the
RewriteRule pattern in per-directory .htaccess files does not begin with a slash, however, if this rule was used in your server config then it would!
This also naturally avoids the rewrite loop since "/remote.php/carddav..." will not match as a valid username (specifically
/ would fail to match).
You could also limit the length of the username, to say between 4 and 20 characters...
If you needed to match any character except a slash (a slash would surely break your destination URL?) then you could use a pattern like: