Detecting and Correcting Dead Shortcuts on Windows

The other day I wondered if all of my local shortcuts, created months and years ago, are still working. Searching for shortcuts and clicking each to determine if the link is dead or alive is a tedious work. So I decided to write a tiny Ruby script to find all dead shortcuts within a directory.

Locating dead shortcuts is done in a function called walk which reads something along the lines of

require 'set'
# gem install win32-shortcut
require 'win32/shortcut'
include Win32

#
# Find all shortcuts recursively starting from +path+ 
# and return those that contain dead links as an array.
#
def walk(path)
  print "Searching for shortcuts "
  lnks = Dir.glob(File.join(File.expand_path(path), '**', '*.lnk'))
  n = lnks.length
  puts "#{n} found"
  
  deads = []
  File.open('errors.txt', 'w') do |ferr|
    ndeads = 0
    nerrors = 0
    lnks.each_with_index do |entry, i|
      begin
        s = Shortcut.open(entry)
        dest = File.expand_path(s.path)
        # Is dead? Note that if you don't have permission 
        # to determine the existance of the path the shortcut will be
        # considered dead.
        unless File.exists?(dest)
          deads << entry
          ndeads += 1
        end
      rescue
        # Opening shortcut failed : not readable, not a shortcut
        nerrors += 1
        ferr.puts("Failed to process shortcut #{entry}")
      end
    end
    puts "Completed (total/current/deads/errors) " + 
         "#{n}/#{n}/#{ndeads}/#{nerrors}"
  end
  deads
end

The number of dead links reported by running walk took me entirely by surprise. Nearly 90 percent of all shortcuts were dead. Soon I discovered the reason for most dead shortcuts: the drive letter assigned to one of the network shares changed earlier this year, which rendered most of the shortcuts useless.

Such situations can be fixed easily through match and replace scripts. Have a look at the following function fix.

# 
# Fix all dead shortcuts by replacing the dead path
# with a new one.
#
# +deads+ is an array of absolute paths to shortcuts
# that contain dead links.
#
# The parameter +replaces+ is an array where each entry
# is a pair (array of two) containing the regex to match
# and the string to use as replacement for whatever is matched
# by the regular expression. The first regex that matches the 
# dead pointer wins the game.
#
def fix(deads, replaces)
  nfixed = 0
  deads.each do |path|
    next unless File.writable?(path)
    s = Shortcut.open(path)
    puts s.path
    params = replaces.detect {|x| s.path =~ x[0]}  
    if params
      s.path = s.path.gsub(params[0], params[1])
      s.save
      nfixed += 1
    end
  end
  puts "Fixed #{nfixed} shortcuts"
end

In combination with walk, fix will automatically correct shortcuts for you.

# The following statement finds all dead shortcuts in 
# 'path/to/shortcuts' recursively. Dead shortcuts are then 
# updated wherever the dead link matches the pattern /^I:\\/. The matched
# part of the link is replaced by 'M:\'. You can supply more than one
# replacement rule, however keep in mind that the first rule that matches
# the link wins.
#
fix(walk('path/to/shortcuts'), [[/^I:\\/, 'M:\\']])

Hope it helps! As always, without warranty of any kind.

About these ads

2 thoughts on “Detecting and Correcting Dead Shortcuts on Windows

  1. How does one run this script on a directory? Which path variable do I adjust in order to execute it on a specific directory?

  2. I should be more specific.

    I run the script on a directory containing almost two thousand links as follows:

    c:\Documents and Settings\Doug.DSP\Recent> ruby DetectDeadShortcuts.rbw

    and it comes back with a command prompt with no visible output. The number of links remains the same as before the execution of the script. I am quite sure that there are numerous dead shortcuts in that directory. I used the Ruby Windows installer 1.92 to install Ruby on my Windows machine. Do I need to add a parameter for the directory at the end of the command prompt?

    Obviously I am a Ruby newbie. I need pointers! lol

    ~Doug

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s