I had the following in my .bash_aliases file:

alias unused='perlcritic --single-policy ProhibitUnusedVariables'

However, I found a few cases where it didn't work. That's when mithaldu told me about warnings::unused. I installed it locally and ran it on some code which had a case that ProhibitUnusedVariables didn't find:

$ unused $some_module $some_module source OK $ perl -Mwarnings::unused -c $some_module 2>&1 | wc -l 34

Whoa! The one area were Perl::Critic modules repeatedly break for me is when I'm dealing with scope issues. It appears to miss where a variable is legitimately declared and used in one sub, but declared and unused in another. It also missed something like the following:

while ( my ($k,$v) = each %hash ) { my $k = munge($v); }

And lucky me! The output of warnings::unused fits the format I'm expecting with the VI::Quickfix code I posted, so I just type :cf and :cn to jump to the next unused variable. Bonus: go ahead and delete them: vim's quickfix mode will note the deleted lines and still jump to the correct line.

Try dropping this in your .vimrc:

au! FileType perl :noremap <leader>c \ :!time perl -Mwarnings::unused -MVi::QuickFix -c %<cr>

With that, every time you hit your leader and 'c', you'll get a quick compile check and a dump of all unused variables. Just hit ':cn" to keep jumping to the next one (or the next error, if you have any).

(Now if I can find some nifty code which finds variables declared outside of the scope they're needed ...)