What's a robust way to insert another extension into a filename?
String manipulation like this is probably done best using regular expressions. If you're not familiar with these, you may want to have a look at the Wikipedia article or the Mathematica tutorial on them first.
The code given below defines a pattern regex
that matches an extension of the type .abcDeF...
at the end of a string (that's accomplished by the $
sign). If that pattern does not match, then the extension is simply added; if the pattern matches, the extension is put in between the rest of the string and the match. Here's the code for that:
appendExtension[filename_, extension_] := Block[{regex},
regex = RegularExpression["\\.[a-z]+$"];
If[Length@StringCases[filename, regex] == 0,
filename <> "." <> extension,
StringReplace[filename, regex -> ("." <> extension <> "$0")]
]
];
appendExtension["/home/me/dir/foo.txt", "123"]
appendExtension["xyz.csv", "123"]
appendExtension["foobar", "123"]
Output:
"/home/me/dir/foo.123.txt"
"xyz.123.csv"
"foobar.123"
A few remarks:
- I'm not sure how you want filenames like
foo.bar.baz
to be handled. The code above replaces this byfoo.bar.123.baz
, i.e. takes only the last extension into account. If you want the new one inserted as the leftmost one, change the regular expression to(\\.[a-z]+)+$
, and the replacement will yieldfoo.123.bar.baz
. - The regex doesn't include upper case extensions or digits. To add these, change
[a-z]
inside the regex to[a-zA-Z0-9]
.
Here's my non-regex solution (but it does use a "String Pattern", which is equivalent to regex). I think it is robust.
insertExtension[fn_String, piece_String] :=
Module[{split = FileNameSplit[fn], temp},
temp = Insert[StringSplit[Last[split], "."], piece, 2];
temp = StringJoin[Riffle[temp, "."]];
FileNameJoin[Append[Most[split], temp]]]
Test:
In[]:= insertExtension["/home/me.em/dir.ab/nomnom.tar.gz", "123"]
Out[]= "/home/me.em/dir.ab/nomnom.123.tar.gz"