Chun Sing Tsui

Coding, Technology, and other Interests

Useful Notepad++ Plugins

Notepad++ is easily one of the best text editors for Windows. I've compiled below a few useful plugins that extends its functionality even further.

If your code contains a mix of spaces and tabs, they will often be inconsistently displayed with different editors. One thing that I've tried to do is making sure my code contains no tabs to avoid inconsistency. This plugin makes it easy to convert tabs to spaces for existing code.

Everyone needs a diff tool. File comparison is always a useful feature when you need to find the differences between two files.

This plugin conveniently allows you to have more than one item in your clipboard, easing copy and paste operations.

A plugin of Artistic Style, which is a C, C++, C#, and Java source code automatic formatter. The one complain that I have with NppAStyle is that it doesn't handle comments very well. Comments will stay at their original position, which is generally not the wanted action.

RunMe is excellent for allowing the execution of the currently open file based on its shell association. Since I've been working with Perl, this allows me to run and test the script easily at the file location.

TextFX contains a slew of functions that are too many to list. It no longer comes with the latest unicode version of Notepad++ (v5.9.6.2), but you can manual install it to get the added features.

Finding Duplicate Files

Another script I wrote to learn more about Perl. I used a script found on PerlMonks as a starting point, and modified it with an additional function of moving all duplicate files into a folder. Again, it is heavily commented to help myself understand the code while I'm writing it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/perl
use Cwd;
use File::Find;
use Digest::MD5;

#-----------------------------------------------------
# This is a script for finding duplicate files in the 
# current directory. It checks for the same file size. 
# If file sizes are different, then files are 
# different. If file sizes are the same, it goes on 
# to check for the MD5 value to determine uniqueness. 
# If MD5 matches, move duplicate files to a folder
#-----------------------------------------------------
# Get current working directory and create duplicate folder directory
$currentDir = cwd();
$dupFolder  = "duplicates";
$dupDir = $currentDir."/".$dupFolder;

# Hash to store filesize as key and an array of filenames as value
%filesSizeHash  = ();
$duplicateCount = 0;
$totalDupSize   = 0;

# Using the file() function, it calls the wanted() function on every 
# file in the current directory

find(\&check_each_file, $currentDir);

# Loop to first find files of the same file size; 
# if there are multiple, check MD5values
foreach my $size (sort {$b <=> $a} keys %filesSizeHash) {
    # Process next filesize unless there are more than one value in
    next unless @{$filesSizeHash{$size}} > 1;
    #print($size."\n");

    # Hash to store MD5 values as key and an array of filenames as value
    my %fileMD5Hash = ();

    # Loop through and get MD5 and store for each file with same size
    foreach my $file (@{$filesSizeHash{$size}}) {
        open(FILE, $file) or next;
        binmode(FILE);
        my $ctx = Digest::MD5->new->addfile(*FILE);
        push @{$fileMD5Hash{$ctx->hexdigest}},$file;
    }

    # Now, take care of file if more than one file has same MD5
    foreach my $hash (keys %fileMD5Hash) {
        next unless @{$fileMD5Hash{$hash}} > 1;
        unless (-d $dupDir){mkdir $dupDir or die;}

        # There are duplicate files to deal with from this point
        # Until the currently accessed array inside the md5 hash has only
        # one item(file), move file into a different directory
        my $count = @{$fileMD5Hash{$hash}};
        for($i = 0; $i < $count-1; $i++){
            $duplicateCount++;
            my $fileName = @{$fileMD5Hash{$hash}}[$i];
            rename($fileName, $dupDir."/".$fileName);
            $totalDupSize = $totalDupSize + $size;
            print("[File moved]: $fileName\n");
        }
    }
}

# Loop to first find files of the same file size; if multiple, check MD5values
$totalDupSize = size_format($totalDupSize);
print("\n[Total number of duplicates found]: $duplicateCount\n");
print("[Toal size of duplicate files]:     $totalDupSize\n");

# Function that is called on every file in the directory of the find() function
sub check_each_file{
    #If the current "file" is a file...
    if (-f) {
        # Get  current file's name
        $currentFileName = $File::Find::name;

        # Get current file's size in bytes
        my $filesize = (stat($currentFileName))[7];

        # Push the file into an hash of arrays declared at the top,
        # with filesize as key and an array of filenames as value
        push( @{ $filesSizeHash {$filesize}}, $_);
    }
}

# Function for formatting the total output size of duplicate files
sub size_format{
   my $size = shift(@_);

   if ($size < 1024) {
      return $size . " bytes";
   }
   if ($size < (1024*1024)) {
      return sprintf("%.2f KB",$size / 1024);
   }
   if ($size < (1024*1024*1024)) {
      return sprintf("%.2f MB",$size / (1024*1024));
   }
   return sprintf("%.2f GB",$size / (1024*1024*1024));
}

Random File Renaming - [Updated]

Update: wrote an undo script that allows you undo the renaming once.

Small script I wrote in Perl for renaming files in the current directory to a random number based on the file extension, useful for randomizing images for slide show purposes.

Simply modify the @extensionArray if you want to add/remove extensions to check against.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/local/bin/perl

#-----------------------------------------------------
# Script to rename files with a random number if 
# extension matches 
#
# Updated: uses a different comparison: now checks 
# for exact match ignoring case
#
# Updated: outputs a file for undo feature
#-----------------------------------------------------

## Define Variable ##
@files = <*>;

#Array variable to hold extensions you may check
@extensionArray = ("jpg", "zip");

#Variable for the largest value of the random #
$randNumCeiling = 100000;

#Simple file counter to keep track of # of files processed
$numFilesRenamed = 0;

#Open a file for writing undo info
open(UNDOFILE, '>_undo_')or die "$!";;

#-----------------------------------------------------
# Loop through all files in the directory
#-----------------------------------------------------
# If it is a file, get the extension
# Checks if the extension is equal to wanted 
# extension(s)
#
# If match, generate random number for filename 
# and rename it
#-----------------------------------------------------
foreach $file (@files)
{
    if (-f $file) {
        # find and ignore all characters that is not a dot, then get the rest
        my $ext = ($file =~ m/([^.]+)$/)[0];

        if(extensionMatch($ext) ) {
            $numFilesRenamed++;
            print "($numFilesRenamed)\n";
            #Old file name
            print UNDOFILE "$file:";
            print "Old file name: $file\n";
            my $newName = int(rand($randNumCeiling));
            rename($file, "$newName.$ext");
            #New file name
            print "New file name: $newName.$ext\n\n";
            print UNDOFILE "$newName.$ext\n";
        }
    }
}
close UNDOFILE;

#-----------------------------------------------------
# Loop through extention array (defined a the top)
# to check for match with the argment passed into
# the function (which is the extension of the file
# currently being processed
#-----------------------------------------------------
# Returns a 1 if extensions match
# else returns 0
#-----------------------------------------------------
sub extensionMatch
{
    $passedInExt = @_[0];
    foreach $extension (@extensionArray){
        #check for exact string ignoring case
        if($extension =~ m/^$passedInExt$/i){
            return 1;
        }
    }
    return 0;
}