#!/usr/bin/perl -w package DVD::Maker; use strict; use Getopt::Long qw(GetOptions); use File::Temp qw(tempdir); use File::Find; use File::Path qw(rmtree mkpath); use File::Spec; use File::Copy; use File::Basename; our $DEBUG = 0; sub usage { print <run unless caller; sub new { my $class = shift; return bless {}, $class; } sub run { my $class = shift; my $self = $class->new(); my $name = ""; my $max_size = 4_508_876 * 1024; my $skip_empty = 0; GetOptions( "h|help" => \&usage, "d|debug" => \$DEBUG, "n|name" => \$name, "s|size" => \$max_size, "e|skip_empty" => \$skip_empty, ); $self->{name} = $name; $self->{max_size} = $max_size; $self->{skip_empty} = $skip_empty, my $dir = shift(@ARGV) || usage(); $self->{folder} = File::Spec->rel2abs($dir); $self->{name} ||= basename($self->{folder}); die "Not a folder: $dir\n" unless -d $self->{folder}; $self->process_dir(); exec("open", "-a", "Disk Utility", ); } #mkisofs -J -r -o TitanicCD.iso -V Titanic TitanicCD/ sub process_dir { my $self = shift; my $dir = $self->{folder}; open(my $du, "-|", "du", "-sk", $dir) || die "du failed: $!"; chomp(my $size = <$du>); close($du); $size =~ s/\s+.*$//; $size *= 1024; dbg("size of $dir: $size"); if ($size < $self->{max_size}) { # approx 4.3GB - stop short of DVD size dbg("making ISO Disk_1.iso"); system("mkisofs", "-J", "-r", "-o", "Disk_1.iso", "-V", $self->{name}, $dir); open(my $mkisofs, "-|", "mkisofs", "-J", "-r", "-o", "Disk_1.iso", "-V", $self->{name}, $dir) || die "mkisofs failed: $!"; while (<$mkisofs>) { chomp; print "\r$_"; } print "\n"; close($mkisofs); return; } $self->{disk_id} = 1; $self->{cur_size} = 0; find({ wanted => sub { $self->wanted(@_) }, no_chdir => 1 }, $dir); # always an extra one to make at the end $self->mk_iso(); } sub dbg { return unless $DEBUG; print @_, "\n"; } sub wanted { my $self = shift; my $curr = $File::Find::name; my $relative = File::Spec->abs2rel( $curr, $self->{folder} ); if (-d $curr) { return if $self->{skip_empty}; # no current temp dir, so create one $self->{temp_dir} ||= tempdir("mk_dvd_XXXXXXXX", TMPDIR => 1); my $path = File::Spec->catdir( $self->{temp_dir}, $relative ); dbg("Creating dir: $path"); mkpath( $path ); return; } my $rel_dir = File::Spec->abs2rel( $File::Find::dir, $self->{folder} ); if (-f $curr) { my $size = -s _; if ( ($self->{cur_size} + $size) > $self->{max_size} ) { dbg("$self->{cur_size} + $size > $self->{max_size}"); $self->mk_iso(); } # no current temp dir, so create one $self->{temp_dir} ||= tempdir("mk_dvd_XXXXXXXX", TMPDIR => 1); my $path = File::Spec->catdir( $self->{temp_dir}, $rel_dir ); unless (-d $path) { dbg("Creating dir: $path"); mkpath( $path ); } dbg("Copying $curr -> $path"); system("cp", $curr, $path) && die "cp failed!"; $self->{cur_size} += $size; } else { warn("don't know how to handle $curr\n"); } return; } sub mk_iso { my $self = shift; my $name = "$self->{name} Disk $self->{disk_id}"; dbg("making ISO Disk_$self->{disk_id}.iso"); open(my $mkisofs, "-|", "mkisofs", "-J", "-r", "-o", "Disk_$self->{disk_id}.iso", "-V", $name, $self->{temp_dir}) || die "mkisofs failed: $!"; while (<$mkisofs>) { chomp; print "\r$_"; } print "\n"; close($mkisofs); $self->{disk_id}++; rmtree($self->{temp_dir}); $self->{temp_dir} = undef; $self->{cur_size} = 0; }