3 # id3fs - a FUSE-based filesystem for browsing audio metadata
4 # Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 use lib '/home/ianb/projects/id3fs/id3fs/lib'; # FIXME: remove
21 use Getopt::Long qw(Configure);
25 $me=($0=~/(?:.*\/)?(.*)/)[0];
33 my @extensions=qw(mp3 flac ogg);
36 Configure(qw(bundling no_ignore_case));
37 my $optret=GetOptions(
38 "verbose|v" => \$verbose,
40 "dir|d=s" => \$basedir,
41 "database|f=s" => \$dbpath,
42 "extensions|e=s" => sub { @extensions=split(/\s+|\s*,\s*/, $_[1]); },
50 usage() if(!@ARGV || !$optret || $help);
51 $init=1 unless($list);
53 unless(defined($basedir) && defined($dbpath))
55 $basedir=ID3FS::DB::find_db($me, $init, @ARGV);
56 exit unless($basedir);
57 my $absbase=Cwd::abs_path($basedir);
60 if(Cwd::abs_path($dir) !~ /^\Q$absbase\E/)
62 die("$me: $dir: must be under basedir $absbase - use --basedir to specify\n");
66 my $db=ID3FS::DB->new($me, $verbose, $init, $basedir, $dbpath);
75 $db->last_update(time());
76 my $base=$db->base_dir();
77 my $abs_base=Cwd::abs_path($base);
80 if(Cwd::abs_path($path) !~ /^$abs_base/)
82 print "$me: $path is outside $base, skipping\n";
84 File::Find::find( {wanted => \&wanted, follow => 1, no_chdir => 1}, $path);
86 my $directories_pruned=$db->prune_directories();
87 if($files_pruned || $directories_pruned)
89 print "$me: pruning removed files from db\n" if $verbose;
92 print "$me: analyzing db\n" if $verbose;
99 if(/.*\.(.*)/) { $ext=lc($1); }
102 print("$_\n") if $verbose;
105 elsif(-f && scalar(grep({ $ext eq lc($_);} @extensions)))
115 $dir=Cwd::abs_path($dir);
116 return unless(opendir(DIR, $dir));
117 my $base=Cwd::abs_path($db->base_dir());
119 my @oldfiles=$db->files_in($dir);
120 my @newfiles=grep { !/^\.\.?$/; } readdir(DIR);
122 @oldfiles=sort @oldfiles;
123 @newfiles=sort @newfiles;
127 for my $file (@oldfiles)
129 unless(exists($hash{$file}))
132 $db->unindex($dir, $file);
140 my @baretags=$db->bare_tags();
141 my $valtags=$db->tags_with_values();
145 print join(', ', sort @baretags), "\n\n";
149 print "TAGS WITH VALUES\n";
150 for my $key (sort keys %$valtags)
152 print "$key: ", join(', ', sort(@{$valtags->{$key}})), "\n";
159 die("Usage: $me [-lvh] [-d basedir] [-f dbpath] [-e mp3,ogg,flac] [--] DIR...\n".
160 " -d|--dir=PATH Base directory of source files (default: ARGV[0])\n".
161 " -f|--database=FILE Path to database file (default: basedir/.id3fs)\n".
162 " -e|--extensions=EXT1,EXT2 File extensions to index (default: mp3, ogg, flac)\n".
163 " -l|list List tags in use\n" .
164 " -v|--verbose Verbose\n".
165 " -h|--help This help\n".
166 " -- End of options\n");
173 id3fs-index - Add files to id3fs index
177 B<id3fs-index> [B<-lvh>] S<[B<-d >I<basedir>]> S<[B<-f >I<dbpath>]> S<[B<-e >I<mp3,ogg,flac>]> [B<-->] [I<DIR>...]
181 Extracts id3 tags from mp3 files (and comment tags from ogg and flac
182 files) and adds them to a sqlite database, ready for mounting
189 =item B<-l> | B<--list>
191 List tags in use in specified database.
193 =item S<B<-d >I<PATH>> | S<B<--dir=>I<PATH>>
195 Specify base directory of source files. All files will be indexed
196 relative to this point.
198 If not specified, defaults to the first non-option argument on the
199 command line. Note that to avoid ambiguities, if more than one
200 directory is specified on the command line, the base directory must
201 be specified explicitly.
203 All files indexed must be under the base directory.
205 =item S<B<-f >I<FILE>> | S<B<--database=>I<FILE>>
207 Database file to use. If not specified, defaults to
208 a hidden file called B<".id3fs"> under the base directory.
210 =item S<B<-e >I<EXT1,EXT2>> | S<B<--extensions=>I<EXT1,EXT2>>
212 File extensions to consider when indexing.
213 Defaults to B<.mp3>, B<.ogg> and B<.flac>.
217 Enable verbose operation.
221 Show a short help message.
231 Index all files in the current directory:
235 Index current directory, printing each subdirectory as it recurses
240 Just index some sub-directories:
242 id3fs-index -d . dir1 dir2
244 Store the database in a custom location:
246 id3fs-index -f ~/.id3fs/index.sqlite .
248 Only index .mp3 and .flac files:
250 id3fs-index -e mp3,flac .
254 Please report any found to ianb@erislabs.net
258 L<id3fsd(8)>, L<MP3::Tag>, L<Audio::Flac::Header>, L<Ogg::Vorbis::Header>
262 Ian Beckwith <ianb@erislabs.net>
264 Many thanks to Aubrey Stark-Toller for help wrangling SQL.
268 The latest version can be found at:
270 L<http://erislabs.net/ianb/projects/id3fs/>
274 Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
276 This program is free software: you can redistribute it and/or modify
277 it under the terms of the GNU General Public License as published by
278 the Free Software Foundation, either version 3 of the License, or
279 (at your option) any later version.
281 This program is distributed in the hope that it will be useful,
282 but WITHOUT ANY WARRANTY; without even the implied warranty of
283 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
284 GNU General Public License for more details.
286 You should have received a copy of the GNU General Public License
287 along with this program. If not, see <http://www.gnu.org/licenses/>.