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/>.
20 use Getopt::Long qw(Configure);
24 $me=($0=~/(?:.*\/)?(.*)/)[0];
32 my @extensions=qw(mp3 flac ogg);
35 Configure(qw(bundling no_ignore_case));
36 my $optret=GetOptions(
37 "verbose|v" => \$verbose,
39 "dir|d=s" => \$basedir,
40 "database|f=s" => \$dbpath,
41 "extensions|e=s" => sub { @extensions=split(/\s+|\s*,\s*/, $_[1]); },
49 usage() if(!@ARGV || !$optret || $help);
50 $init=1 unless($list);
52 unless(defined($basedir) && defined($dbpath))
54 $basedir=ID3FS::DB::find_db($me, $init, @ARGV);
55 exit unless($basedir);
56 my $absbase=Cwd::abs_path($basedir);
59 if(Cwd::abs_path($dir) !~ /^\Q$absbase\E/)
61 die("$me: $dir: must be under basedir $absbase - use --basedir to specify\n");
65 my $db=ID3FS::DB->new($me, $verbose, $init, $basedir, $dbpath);
74 $db->last_update(time());
75 my $base=$db->base_dir();
76 my $abs_base=Cwd::abs_path($base);
79 if(Cwd::abs_path($path) !~ /^$abs_base/)
81 print "$me: $path is outside $base, skipping\n";
83 File::Find::find( {wanted => \&wanted, follow => 1, no_chdir => 1}, $path);
85 my $directories_pruned=$db->prune_directories();
86 if($files_pruned || $directories_pruned)
88 print "$me: pruning removed files from db\n" if $verbose;
91 print "$me: analyzing db\n" if $verbose;
98 if(/.*\.(.*)/) { $ext=lc($1); }
101 print("$_\n") if $verbose;
104 elsif(-f && scalar(grep({ $ext eq lc($_);} @extensions)))
114 $dir=Cwd::abs_path($dir);
115 return unless(opendir(DIR, $dir));
116 my $base=Cwd::abs_path($db->base_dir());
118 my @oldfiles=$db->files_in($dir);
119 my @newfiles=grep { !/^\.\.?$/; } readdir(DIR);
121 @oldfiles=sort @oldfiles;
122 @newfiles=sort @newfiles;
126 for my $file (@oldfiles)
128 unless(exists($hash{$file}))
131 $db->unindex($dir, $file);
139 my @baretags=$db->bare_tags();
140 my $valtags=$db->tags_with_values();
144 print join(', ', sort @baretags), "\n\n";
148 print "TAGS WITH VALUES\n";
149 for my $key (sort keys %$valtags)
151 print "$key: ", join(', ', sort(@{$valtags->{$key}})), "\n";
158 die("Usage: $me [-lvh] [-d basedir] [-f dbpath] [-e mp3,ogg,flac] [--] DIR...\n".
159 " -d|--dir=PATH Base directory of source files (default: ARGV[0])\n".
160 " -f|--database=FILE Path to database file (default: basedir/.id3fs)\n".
161 " -e|--extensions=EXT1,EXT2 File extensions to index (default: mp3, ogg, flac)\n".
162 " -l|list List tags in use\n" .
163 " -v|--verbose Verbose\n".
164 " -h|--help This help\n".
165 " -- End of options\n");
172 id3fs-index - Add files to id3fs index
176 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>...]
180 Extracts id3 tags from mp3 files (and comment tags from ogg and flac
181 files) and adds them to a sqlite database, ready for mounting
188 =item B<-l> | B<--list>
190 List tags in use in specified database.
192 =item S<B<-d >I<PATH>> | S<B<--dir=>I<PATH>>
194 Specify base directory of source files. All files will be indexed
195 relative to this point.
197 If not specified, defaults to the first non-option argument on the
198 command line. Note that to avoid ambiguities, if more than one
199 directory is specified on the command line, the base directory must
200 be specified explicitly.
202 All files indexed must be under the base directory.
204 =item S<B<-f >I<FILE>> | S<B<--database=>I<FILE>>
206 Database file to use. If not specified, defaults to
207 a hidden file called B<".id3fs"> under the base directory.
209 =item S<B<-e >I<EXT1,EXT2>> | S<B<--extensions=>I<EXT1,EXT2>>
211 File extensions to consider when indexing.
212 Defaults to B<.mp3>, B<.ogg> and B<.flac>.
216 Enable verbose operation.
220 Show a short help message.
230 Index all files in the current directory:
234 Index current directory, printing each subdirectory as it recurses
239 Just index some sub-directories:
241 id3fs-index -d . dir1 dir2
243 Store the database in a custom location:
245 id3fs-index -f ~/.id3fs/index.sqlite .
247 Only index .mp3 and .flac files:
249 id3fs-index -e mp3,flac .
253 Please report any found to ianb@erislabs.net
257 L<id3fsd(8)>, L<MP3::Tag>, L<Audio::Flac::Header>, L<Ogg::Vorbis::Header>
261 Ian Beckwith <ianb@erislabs.net>
263 Many thanks to Aubrey Stark-Toller for help wrangling SQL.
267 The latest version can be found at:
269 L<http://erislabs.net/ianb/projects/id3fs/>
273 Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
275 This program is free software: you can redistribute it and/or modify
276 it under the terms of the GNU General Public License as published by
277 the Free Software Foundation, either version 3 of the License, or
278 (at your option) any later version.
280 This program is distributed in the hope that it will be useful,
281 but WITHOUT ANY WARRANTY; without even the implied warranty of
282 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
283 GNU General Public License for more details.
285 You should have received a copy of the GNU General Public License
286 along with this program. If not, see <http://www.gnu.org/licenses/>.