user
Before writing to a file it is often advisable to make a backup of the original.
Creating such a backup file is however also not without pitfalls.

In this task you should create a backup file from an existing file and then write new text to the old file.
The following issues should be handled:

* avoid making a copy of the file but instead rename the original and then write a new file with the original filename.
* if a copy needs to be made, please explain why rename is not possible.
* keep in mind symlinks, and do not rename or copy the link but the target. (If there is a link `foo -> bar/baz`, then `bar/baz` should be renamed to `bar/baz.backup` and then the new text should be written to `bar/baz`.)
* it is assumed that you have permission to write in the target location, thus permission errors need not be handled.
* you may choose the backup filename per preference or given limitations. (It should somehow include the original filename however.)
* please try to avoid executing external commands, and especially avoid calling a shell script.

Some examples on this page assume that the original file already exists. They might fail if some user is trying to create a new file.
assistant
(formerly Perl 6)

**Works with**: Rakudo version 2017.10

```
# Back up the given path/filename with a default extension .bk(n)
# where n is in the range 1 - $limit (default 3).
# Prints 'File not found' to STDERR if the file does not exist.
# Will not do anything if limit is set to less than 1.
# Will not follow symlinks by default.

sub backup (Str $filepath, Int :$limit = 3, Str :$ext = 'bk', Bool :$follow-symlinks = False) {
    my $abs = $follow-symlinks ?? $filepath.IO.resolve.absolute !! $filepath.IO.absolute;
    for (1 ..^ $limit).reverse -> $bnum {
        if "{$abs}.{$ext}{$bnum}".IO.e {
            "{$abs}.{$ext}{$bnum}".IO.rename: "{$abs}.{$ext}{$bnum + 1}";
        }
    }
    if $abs.IO.e {
        if $limit > 0 {
            $abs.IO.rename: "{$abs}.{$ext}1";
            my $in  = "{$abs}.{$ext}1".IO.open :r :bin or note $! and return False;
            my $out = $abs.IO.open :w :bin or note $! and return False;
            my $buffer-size = 32768; # 32Kb
            while my $buf = $in.read($buffer-size) { $out.write($buf) };
            close $in;
            close $out;
        }
    } else {
        note "File not found: $abs" and return False;
    }
    $abs # return filepath on success
}

# back up this program
backup $*PROGRAM-NAME;

# Optionally, specify limit, back-up extension pattern and whether to follow symlinks.
# Optional parameters can be in any order, in any combination.
backup 'myfile', :follow-symlinks, :limit(2), :ext('bak');

```