Backup file with .bak _before_ filename extension
Might be as simple as
cp file.{ext,bak.ext}
bash {} expansion expands to all combinations (unlike [] expantion which lists existing files. So it generates two file names.
The { .... , .... } provides two options, so you get file.ext and file.bak.ext
In your script you would use
cp $FILE.{$EXTENTION,bak.$EXTENTION}
And to break up the FILENAME into the two halves you can use
FILE=${FILENAME%.*}
EXTN=${FILENAME##*.}
${VAR%xxxxx} will return the left side of what is in VAR up to the matching pattern, in the case above the pattern is .* so you get everything except the last .*
${VAR##xxxxx} will return the right side of what is in VAR, after the matching pattern. The double hash means get the biggest possible match, in case there is more than one possble match.
To make your script save, check for cases where after obtaining FILE and EXTENTION, that they are not the same thing. This will happen in cases where the file name doesn't have an extention.
A sub-section of your script might look like this:
ls *html | while read FILENAME
do
FILE=${FILENAME%.*}
EXTN=${FILENAME##$FILE}
cp $FILE{$EXTN,.bak$EXTN}
done
You can always use a function:
backup()
for i do
case ${i##*/} in
(?*.?*) cp -iv -- "$i" "${i%.*}.bak.${i##*.}";;
(*) cp -iv -- "$i" "$i.bak"
esac
done
${i##*/}
is the basename of $i
(that is $i
with everything up to the rightmost /
removed), because we don't want to consider bar/file
as the extension in foo.bar/file
.
Then we check whether $i
contains an extension, that is if it contains at least one dot
character with characters on both sides (?*
is any one character followed by 0 or more characters, so it's one or more characters). We can't do *.*
otherwise we'd backup ~/.bashrc
as ~/.bak.bashrc
for instance.
That syntax above is POSIX except for the -v
(for verbose) option to cp
which is a GNU extension also found in a few other implementations like BSDs'.
Then you can do things like:
backup foo.php bar.html baz<Tab>...
Or:
backup *.php
Without having to worry about losing data (-i
will ask for confirmation before overwriting a file, see also the -b
option with GNU cp
) or not picking the right name.
I can't offhand think of a way to do this with tab completion, except possibly to also keep a copy of the file name without the extension, so you can add "bak.php" in one go. But my solution to this would be a small shell script, that takes a file name as input and copies it to "firstpart.bak.extension".