2

This does not work:

$ tar -cf /tmp/z.tar -C /space/myroot -s '/^\.svn\/patches/__patches' src .svn/patches
tar: Invalid regular expression: trailing backslash (\)
Also no good:
$ tar -cf /tmp/z.tar -C /space/myroot -s '/^\\.svn\\/patches/__patches' src .svn/patches
tar: Invalid replacement flag _
Every combination of backslashes (up to 4) and quoting gives me one of those two errors. However I know the first one works in sed:
$ tar -cf /tmp/z.tar -C /space/myroot src .svn/patches
$ tar -tf /tmp/z.tar | sed 's/^\.svn\/patches/__patches/'
src/a.c
src/b.c
__patches/A.patch
__patches/B.patch
Also I know I can cop-out and do this:
$ tar -cf /tmp/z.tar -C /space/myroot -s '/^.svn.patches/__patches' src .svn/patches
-- but I don't really want to.
user9645
  • 6,286
  • 6
  • 29
  • 43

1 Answers1

6

From man bsdtar:

-s pattern
....
where old is a basic regular expression
...

Basic regular expression should work with \/. Sadly bsdtar is incorrectly written here, and does not handle escaping correctly.

From bsdtar/subst.c:

end_pattern = strchr(rule_text + 1, *rule_text);

rule_text is a string char * which is passed with the string you pass to -s option, so it has the string /^\.svn\/patches/__patches. The end_pattern should point to the last character of the pattern (ie. to the / in from of /__patches). However as simple strchr is used, so the first / found is used (the character in \/), escaped or not, it is used. The error:

tar: Invalid regular expression: trailing backslash (\)

comes from regcomp trying to parse the regular expression ^\.svn\ (as this is the part stripped between the two /). As there is nothing behind the trailing backslash \ in the expression, it throws an error (and is correct - a trailing backslash is there). One could think of posting a bug report to bsdtar developers, but it's probably not really worth fixing.

Note that the syntax for -s is /old/new/. There is a trailing / in the pattern, which you are missing. After the last / you can specify flags.

You can however workaround the issue with:

bsdtar -s '#\.svn/patches#__patches#'

Any character will work for the /.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 1
    Thanks - I didn't think to try alternate delimiters since the man page for tar did not mention it. Also the missing delimiters in my question was just a cut/paste error. – user9645 Jan 09 '19 at 12:53
  • This is why as much as I like to say to beginners that StackOverflow isn't as good as they think it is because of easily abusable mindless copy-pastery (and sometimes also why that is bad, as some don't have the experience to understand that), I don't allow me to state plainly that they shouldn't use it, as there is still plenty of useful gems like this. This info would take me ages to find out. – Doodad Nov 10 '21 at 21:48