The two options I use are Drush and a custom script.

For Drush, you can use `drush pm-list`:


    $ drush help pm-list
    Show a list of available extensions (modules and themes).
    
    Options:
     --type                                    Filter by extension type. Choices:
                                               module, theme.
     --status                                  Filter by extension status. Choices:
                                               enabled, disable and/or 'not
                                               installed'. You can use multiple
                                               comma separated values. (i.e.
                                               --status="disabled,not installed").
     --package                                 Filter by project packages. You can
                                               use multiple comma separated values.
                                               (i.e. --package="Core -
                                               required,Other").
     --core                                    Filter out extensions that are not
                                               in drupal core.
     --no-core                                 Filter out extensions that are
                                               provided by drupal core.
     --pipe                                    Returns a space delimited list of
                                               the names of the resulting
                                               extensions.
    
    
    Aliases: pml

I also wrote this script for Drupal 6.  You need to edit the bootstrap for Drupal 7, and you may also want to tweak the path checking.  I put this in a file called modules.php in my DOCROOT and add access restriction around it to prevent it from being called from the wild.

    <?php
    include_once './includes/bootstrap.inc';
    drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
    header('Content-Type: text/plain');
    
    $files = drupal_system_listing('/\.module$/', 'modules', 'name', 0);
    
    system_get_files_database($files, 'module');
    
    ksort($files);
    
    $core_installed = array();
    $core_enabled = array();
    $core_disabled = array();
    
    $contrib_installed = array();
    $contrib_enabled = array();
    $contrib_disabled = array();
    
    foreach ($files as $info) {
      $filename = $info->filename;
      $name = $info->name;
      $status = $info->status;
      
      $contrib = strpos($filename, "sites/all/modules/") === 0;
      
      if ($contrib) {
        $contrib_installed[] = $name;
        if ($status) $contrib_enabled[] = $name;
        else $contrib_disabled[] = $name;
      } else {
        $core_installed[] = $name;
        if ($status) $core_enabled[] = $name;
        else $core_disabled[] = $name;
      }
    }
    
    print "Installed Core Modules: " . join(", ", $core_installed) . "\n\n";
    print "Enabled Core Modules: " . join(", ", $core_enabled) . "\n\n";
    print "Disabled Core Modules: " . join(", ", $core_disabled) . "\n\n";
    
    print "Installed Contrib Modules: " . join(", ", $contrib_installed) . "\n\n";
    print "Enabled Contrib Modules: " . join(", ", $contrib_enabled) . "\n\n";
    print "Disabled Contrib Modules: " . join(", ", $contrib_disabled) . "\n\n";

This script can be called with drush using: `drush scr modules.php`