PERL - Mass A Record IPv4 to IPv6 Replacement


Jan 12, 2017
Hello all,

I like many thanks for the previous post, currently I'm working on a new project. This one is actually very neat and I'm pretty sure we will all need it from the future. Especially those that in the hosting industry where you host plenty of DNS records. I love the thank you from everyone, so now when I post a script I actually do spend time to write comment into the script and write it in a way that we can all read from and navigate through easily.

What does this script do. This script was written by me in Perl, it read all name record files in a specified directory. You have to configure the extension and the directory to test it. You give the config an ipv4 record and an ipv6 record. It will search through every files in that directory with that naming context one at a time. The script can then either replace the IPv4 record with the IPv6 record or it can add the IPv6 record to the files. For adding it will only add if there is not another IPv6 record with that exact same value on file(this is very good, so you don't have a script that keep on adding :) ).

The limitation of this currently is that you can only deal with A name record. It will only change one IP at a time. This version is good for anyone who want or need to learn from. I'm working on a pro version of this one and if you need it you can contact me.

To test this script create a directory with DNS name record file in it. Give the directory, a lot of them. Create a temp directory, put the configuration into the script. Run the script. I did do some extensive testing on it but if there is a bug I would like to hear your comment. Any comment is appreciated. Thank you.

# Copyright notice. 
# Please include this in redistribution.
# Original author kevinhng86 @ FAI Hosting Solution.
# This is free to use for any purpose that is not unlawful for free of charge.
# This script follow CDDL-1.0 license protocol, to use this script for any purpose you are agreeing to CDDL-1.0.
# CDDL-1.0 license can be view from the link below.

use strict;

package config;
    our $dir = "./yourdir"; #directory to look into to search for DNS name file record file
    our $ext = "ns"; #extension of file, dont put dot here
    our $ipv4 = "123:123:123:123"; #ipv4 address to look for
    our $ipv6 = "2001:db8:3:4::1"; #ipv6 address to change or replace to
    our $tempdir = "./tmp"; #temporary directory

package function;
sub getFileList{
  our ($getdir, $getname) = @_; # to use this function string directory path first, string extension after
    our @list = ();  # array to hold all file name with the config extenstion
    our @output = (); # output array
    # Open directory and search for file with extension, compile an array with all file names that is found
    opendir my $DIR,  $getdir or die "Cannot open directory: $!"; 
    @list = grep( /\.$getname$/ ,readdir($DIR));

    # If directory name input doesn have / then add / to the end of it
    if (!($getdir =~ /\/$/)) { $getdir = $getdir . "/";};

    # Add file name to full path for each file is found and push the result into an output array.
    for (our $i = 0; $i < scalar(@list); $i++){
        our $str = $getdir . @list[$i];
        push @output, $str;
    # This function can return 2 result, the array @list is for filename only, array @output is file name with full path, configure to desire
    return @output;

sub faiIPv4ToIPv6{
    our ($inarray, $ipv4, $ipv6, $tempdir, $operation) = @_;
    our @filelist = @{ $inarray };
    our @repcountarr = (); # storing information
    our %repcounthash = {}; # storing how many record is replace from a file into a hash;
    our $repcount = 0; # each time a row is replace with record count will increase
    our $tempfile = "faitemp.tmp"; # temporary file name
    our $tempstr = ""; # Temporary string to work with, for operation replace
    our $tempstradd = ""; # Temporary sring for operation add
    our $tempdirexist = ""; #variable to check if temporary directory pre-exist for script clean up

    # check operation, only support add or replace
    if ($operation ne "add" && $operation ne "replace") { die "only support operation add or replace"  } ;
    # create a string with temp file full path, first check to see if there is a splash on the end of temp dir if there is not add a splash
    if (!($tempdir =~ /\/$/)) { $tempdir = $tempdir . "/";};
    our $tempfullpath = $tempdir . $tempfile;
    # check if temp dir is exist if not create, set tempdirexist in both case for clean up after 
    if (-d $tempdir){
        $tempdirexist = "true";
    if (!-d $tempdir){
        $tempdirexist = "false";
        unless(mkdir $tempdir) {
             die "Unable to create $tempdir\n";
    if (-e $tempfullpath) {
        die "temporary file $tempfullpath exist.\nYou might have another program use the same name or this script crash while running, check to see if any information is needed\n";
    for ( our $i = 0; $i < scalar(@filelist); $i++){
            $repcount = 0; # Set replace count to 0 each time one file is loop through
            %repcounthash = {}; # Reset all rep count hash property after every use.
            our @content = () ; # Read content into this array, each line equal to one array 
            our $arrcount = 0; # everytime a newline is read from the file this count will plus one so array does not save to the same one everytime
            our @contentadd = (); # when adding temporary save onto this array
            our $arraddcount = 0; # everytime there is a modification to the add array this have to be increase

            # open file and read all content into an array
            open(ORGIN, "<"."@filelist[$i]") or die "Could not open file '@filelist[$i]' $!" ;
                while (our $row = <ORGIN>){
                    @content[$arrcount] = $row;
                    $arrcount = $arrcount + 1;
            # This is simple, if replace just replace the ipv4 with ipv6 and replace A with AAAA
            if ($operation eq "replace" ){
                for (our $id = 0; $id < scalar(@content); $id++){
                    if ( index(@content[$id], $ipv4) != -1 && index(@content[$id], "A"  ) != -1 ){
                         @content[$id] =~ s/$ipv4/$ipv6/g;
                         @content[$id] =~ s/A/AAAA/g;
                         $repcount = $repcount + 1;
            # Operation add, check if there is ipv4 value. If match check to see if weather an ipv6 record exist for ipv4 record.
            # Only add if there is not another ipv6 record with same value exist.
            # append the information to a difference array so that the record are add below the original record.
            if ($operation eq "add"){
                for (our $id = 0; $id < scalar(@content); $id++){
                    @contentadd[$arraddcount] = @content[$id];
                    $arraddcount = $arraddcount + 1;
                    if ( index(@content[$id], $ipv4  ) != -1 && index(@content[$id], "A"  ) != -1 ){
                         $tempstr = @content[$id];
                         $tempstr =~ s/$ipv4/$ipv6/g;
                         $tempstr =~ s/A/AAAA/g;
                         if ( !(grep { $_ eq $tempstr} @content) ){
                             $repcount = $repcount + 1;
                             @contentadd[$arraddcount] = $tempstr;
                             $arraddcount = $arraddcount +1;
                @content = @contentadd;
            # Open a temporary file to write to and then copy that file to the original just read from.
            # This way we do not open the original again incase script failure during write, crash, or unexpected program behaviour on difference platform.
            open(TEMP, ">"."$tempfullpath") or die "Could not open file '$tempfullpath' $!";
                for (our $id = 0; $id < scalar(@content); $id++){
                    print TEMP @content[$id] . "\n";
            close( TEMP );
            # Replace the original file with a temp file. 
            rename ($tempfullpath, @filelist[$i] );

            # produce how many records was replace or add in which file.    
            $repcounthash{"operation"} = $operation;
            $repcounthash{"count"} = $repcount;
            $repcounthash{"file"} = @filelist[$i];        
            push @repcountarr, {%repcounthash};

    # if the temp directory was created by this script delete it, if not left it intact
    if ( $tempdirexist eq "false" ){
        rmdir $tempdir;
        if(-e $tempdir) 
            print "Temporary directory '$tempdir' could not be deleted";
    return @repcountarr;

package main;

our @test = function::getFileList($config::dir, $config::ext);
our @result = function::faiIPv4ToIPv6([@test], $config::ipv4, $config::ipv6, $config::tempdir, "add");

for (our $i = 0; $i < scalar(@result); $i++){
    if (  @result[$i]->{"operation"} eq "replace"){
    print @result[$i]->{"operation"} . " " . @result[$i]->{"count"} . " record(s) from " . @result[$i]->{"file"} . "\n";
    if (  @result[$i]->{"operation"} eq "add"){
    print @result[$i]->{"operation"} . " " . @result[$i]->{"count"} . " record(s) to " . @result[$i]->{"file"} . "\n";
Older Threads
Newer Threads
Recommended Threads

Latest Hosting OffersNew Reviews


Tag Cloud

You are using an out of date browser. It may not display this or other websites correctly.
You should upgrade or use an alternative browser.