.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 1, 2022
+.Dd December 10, 2023
.Dt TAR 1
.Os
.Sh NAME
Modify file or archive member names according to
.Pa pattern .
The pattern has the format
-.Ar /old/new/ Ns Op ghHprRsS
+.Ar /old/new/ Ns Op bghHprRsS
where
.Ar old
is a basic regular expression,
The optional trailing p specifies that after a successful substitution
the original path name and the new path name should be printed to
standard error.
+The optional trailing b specifies that the substitution should be
+matched from the beginning of the string rather than from right after the
+position at which the previous matching substitution ended.
Optional trailing H, R, or S characters suppress substitutions
for hardlink targets, regular filenames, or symlink targets,
respectively.
struct subst_rule *next;
regex_t re;
char *result;
- unsigned int global:1, print:1, regular:1, symlink:1, hardlink:1;
+ unsigned int global:1, print:1, regular:1, symlink:1, hardlink:1, from_begin:1;
};
struct substitution {
rule->regular = 1; /* Rewrite regular filenames. */
rule->symlink = 1; /* Rewrite symlink targets. */
rule->hardlink = 1; /* Rewrite hardlink targets. */
+ rule->from_begin = 0; /* Don't match from start. */
while (*++end_pattern) {
switch (*end_pattern) {
+ case 'b':
+ case 'B':
+ rule->from_begin = 1;
+ break;
case 'g':
case 'G':
rule->global = 1;
{
const char *path = name;
regmatch_t matches[10];
+ char* buffer = NULL;
size_t i, j;
struct subst_rule *rule;
struct substitution *subst;
continue;
}
+ if (rule->from_begin && *result) {
+ realloc_strcat(result, name);
+ realloc_strcat(&buffer, *result);
+ name = buffer;
+ (*result)[0] = 0;
+ }
+
while (1) {
if (regexec(&rule->re, name, 10, matches, 0))
break;
case '9':
realloc_strncat(result, rule->result + j, i - j - 1);
if ((size_t)(c - '0') > (size_t)(rule->re.re_nsub)) {
+ free(buffer);
free(*result);
*result = NULL;
return -1;
if (got_match)
realloc_strcat(result, name);
+ free(buffer);
+
if (print_match)
fprintf(stderr, "%s >> %s\n", path, *result);
assertFileContents("foo", 3, "test4/in/d1/bar");
assertFileContents("bar", 3, "test4/in/d1/baz");
+ /*
+ * Test 4b: Multiple substitutions behavior with option b).
+ */
+ assertMakeDir("test4b", 0755);
+ systemf("%s -cf test4b.tar in/d1/foo in/d1/bar",
+ testprog);
+ systemf("%s -xf test4b.tar -s /oo/ar/ -s }ar}az}b -C test4b",
+ testprog);
+ assertFileContents("foo", 3, "test4b/in/d1/faz");
+ assertFileContents("bar", 3, "test4b/in/d1/baz");
+
/*
* Test 5: Name-switching substitutions when extracting archive.
*/