SoFunction
Updated on 2025-04-07

Perl batch adds Copyright copyright information

For all input files, if there is no copyright information, add copyright information, otherwise do nothing, and backup the original file with .bak.

Starting with the following program I use (first try to back up the entered file):

#!usr/bin/perl -w
$^I = ".bak";
my %do_these;

foreach (@ARGV){
  print $_;
 $do_these{$_} = 1;
}

while(<>){
 if(/^## Copyright/){
  delete $do_these{$ARGV};
 }
}

@ARGV = sort keys %do_these;
while(<>){
 if(/^#!/){
  $_ .= "## Copyright (C) 2011 by yujianjun";
 }
 print;
}

The result: The original and backup files are all blank, which is really bad. (Remember to make a backup when testing the program in the future).
Analysis reasons:

Mainly due to the error in using $^I. Let’s first take a look at how $^I works:

$^I default value undef, which will not affect the program. If it is assigned a value to a string (such as ".bak" in the program), the program will perform a backup operation and add the string to the original file name to become the extension of the backup file name. When using the diamond operator to open a file, the perl operation is to first change the opened file name to a file name with an extension name, then create a new file with the original file name, and then read the file contents one by one and make some changes to it, and save it to the new file. This is equivalent to modifying the file content and backing up the old files. Of course, if the value is undef, the old files will not be backed up.

Since the above program put $^I = ".bak"; in the front, but there are two file read operations afterwards. Assuming that the file is read in, the first time while(<>) turns the original file into it. Then create a new empty file and name it; but the new file will only be written to disk when the program ends. Therefore, when the file is read for the second time, the blank will be turned into, which will overwrite the first backup file, and then create a new blank file. At this time, the contents of both the original file and the backup file are all blank.

After understanding the working principle of $^I, the program will be easily modified:

Just put $^I = ".bak"; before the last file read operation while(<>), as follows:

#!usr/bin/perl -w

my %do_these;
@ARGV = ("","","");

foreach (@ARGV){
  print $_;
 $do_these{$_} = 1;
}

while(<>){
 if(/^## Copyright/){
  delete $do_these{$ARGV};
 }
}

@ARGV = sort keys %do_these;
$^I = ".bak";
while(<>){
 if(/^#!/){
  $_ .= "## Copyright (C) 2011 by yujianjun";
 }
 print;
}

This is basically enough, and everyone can modify it as needed. I hope everyone supports me more.