How to escape chars in BSD tar path substitution o

2019-08-28 15:16发布

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.

1条回答
神经病院院长
2楼-- · 2019-08-28 15:55

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 /.

查看更多
登录 后发表回答