peterr has asked for the wisdom of the Perl Monks concerning the following question:

I'm using a Perl script to convery KMail emails to Claws email. There were a few errors

#!/usr/bin/perl -w # * This file is free software; you can redistribute it and/or modify + it # * under the terms of the GNU General Public License as published by # * the Free Software Foundation; either version 2 of the License, or # * (at your option) any later version. # * # * This program is distributed in the hope that it will be useful, b +ut # * WITHOUT ANY WARRANTY; without even the implied warranty of # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # * General Public License for more details. # * # * You should have received a copy of the GNU General Public License # * along with this program; if not, write to the Free Software # * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 021 +10-1301, USA. # * # * Copyright 2003-2007 Paul Mangan <paul@claws-mail.org> # * # * 2007-02-25: several fixes for kmail 1.9.6 # --kmaildir now expects the full path # renamed from maildir2claws-mail.pl to kmail-mailbox2claws-ma +il.pl # * 2003-10-01: add --debug and --dry-run options # * 2003-09-30: updated/improved by Matthias Förste <itsjustme@users. +sourceforge.net> # * 2003-05-27: version one ## script name : kmail-mailbox2claws-mail.pl ## script purpose : convert a Kmail mailbox into a Claws Mail mailbox ## USAGE: kmail-mailbox2claws-mail.pl --kmaildir=/full/path/to/kmail/m +ailbox ## tested with Kmail version 1.9.6 use strict; use Getopt::Long; use File::Find; my $kmaildir = ''; my $iNeedHelp = ''; # dont actually change anything if set(useful in conjunction with debu +g) my $PRETEND = ''; # print debug info if set my $DEBUG = ''; my $claws_tmpdir = "$ENV{HOME}/claws_tmp"; GetOptions("kmaildir=s" => \$kmaildir, "help" => \$iNeedHelp, "dry-run" => \$PRETEND, "debug" => \$DEBUG); if ($kmaildir eq "" || $iNeedHelp) { if (!$iNeedHelp) { print "No directory name given\n"; } print "Use the following format:\n"; print "\tkmail-mailbox2claws-mail.pl --kmaildir=full-path-to-kmail +-dir\n\n"; exit; } my $count = 1; my $MAIL_dir = "$kmaildir"; my $find_opts = { wanted => \&process }; if (-d $MAIL_dir) { find($find_opts , ($MAIL_dir)); } else { print "\n$MAIL_dir is not a directory !\n"; exit; } unless ($PRETEND) { mkdir("$claws_tmpdir", 0755); system("mv $claws_tmpdir $ENV{HOME}/Mail"); print "\n\nSucessfully converted mailbox \"$MAIL_dir\"\n"; print "Start claws-mail and right-click \"Mailbox (MH)\" and "; print "select \"Rebuild folder tree\"\n"; print "You may also need to run \"/File/Folder/Check for "; print "new messages in all folders\"\n\n"; } print "\n"; exit; sub process() { if (-d) { process_dir($File::Find::dir); } else { process_file($File::Find::name); } } sub process_dir() { my $direc = shift(); $DEBUG && print "\nDIR $direc"; if ($direc !~ m/^drafts$/ && $direc !~ m/^outbox$/ && $direc !~ m/^trash$/ && $direc !~ m/^inbox$/) { my $tmpdir = $direc; $tmpdir =~ s/^$MAIL_dir//; $tmpdir =~ s/\/sent-mail$/sent/; $tmpdir =~ s/\/cur$//; $tmpdir =~ s/\/new$//; $tmpdir =~ s/^\///; $tmpdir =~ s/\.directory//g; $tmpdir =~ s/\.//g; my $newdir = "$claws_tmpdir/$tmpdir"; $DEBUG && print qq{\n>>> -e "$newdir" || mkdir("$newdir")}; $PRETEND || -e "$newdir" || mkdir("$newdir"); } } sub process_file { my $file = shift; $DEBUG && print "\nFILE $file"; my $nfile; my $tmpfile = $file; $tmpfile =~ s|^$kmaildir||; if ($tmpfile =~ m/\/cur\// || $tmpfile =~ m/\/new\//) { $tmpfile =~ s/\/new//; $tmpfile =~ s/\/cur//; my @spl_str = split("/", $tmpfile); pop(@spl_str); push(@spl_str, "$count"); foreach my $spl_str (@spl_str) { $spl_str =~ s/\.directory$//; $spl_str =~ s/^\.//; $spl_str =~ s/^sent-mail$/sent/; } $nfile = join("/", @spl_str); $nfile = $claws_tmpdir.$nfile; } if (-e "$file" && $nfile ne "") { $DEBUG && print qq{\n+++ cp "$file" "$nfile"}; $PRETEND || system("cp \"$file\" \"$nfile\""); $count++; } }

cp: cannot create regular file '/home/********/claws_tmp/*******/Misc. (PO,NRMA,etc)/711': No such file or directory

Is this simply because the file is attempted to be copied before the path exists ? How do I fix that please

Also this error ...

Use of uninitialized value $nfile in string ne at kmail-mailbox2claws-mail.pl line 149.

It is defined at libe 125, but not initialised; is that all that needs doing there ?

Replies are listed 'Best First'.
Re: Convert KMail emails to Claws
by kcott (Archbishop) on Apr 27, 2017 at 06:21 UTC

    G'day peterr,

    "cp: cannot create ... Is this simply because the file is attempted to be copied before the path exists ?"

    No doubt:

    $ > fred $ cp fred not_a_real_dir/ cp: cannot create regular file 'not_a_real_dir/': Not a directory $ mkdir not_a_real_dir/ $ cp fred not_a_real_dir/ $
    "How do I fix that please"

    See the Perl function mkdir; and the make_path() function in the builtin module File::Path.

    "Use of uninitialized value $nfile in string ne ... It is defined ... not initialised; is that all that needs doing there ?"

    Yes, being defined is not the same as being initialised: that's what it's telling you.

    $ perl -wE 'my $x; say $x ne "" ? 1 : 0' Use of uninitialized value $x in string ne at -e line 1. 0 $ perl -wE 'my $x = ""; say $x ne "" ? 1 : 0' 0 $

    — Ken

      Thanks Ken; that fixed the variable not being initialised.
Re: Convert KMail emails to Claws
by shmem (Chancellor) on Apr 27, 2017 at 06:21 UTC
    Is this simply because the file is attempted to be copied before the path exists ? How do I fix that please

    That could very well be.

    use File::Basename; use File::Path; ... my $nfile = ''; ... if (-e "$file" && $nfile ne "") { my $dir = dirname $nfile; if( !-d $dir ) { make_path($dir) or die "Can't create $dir: $!\n"; } $DEBUG && print qq{\n+++ cp "$file" "$nfile"}; $PRETEND || system("cp \"$file\" \"$nfile\""); $count++; }

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

      Thanks. I included both the 'Use' statements, and that code, however the error was "Undefined subroutine &main::make_path"

      Possibly the 'Use' needs to be defined globally or I put the 'Use' with the sub routine ?

        Replace use File::Path; with use File::Path qw(make_path);, it is not exported by default.

Re: Convert KMail emails to Claws
by poj (Abbot) on Apr 27, 2017 at 06:34 UTC
    ..before the path exists ? How do I fix that please

    Check the directories are being created

    # replace this line # $PRETEND || -e "$newdir" || mkdir("$newdir"); # with this unless ($PRETEND || -e $newdir){ mkdir($newdir) or die "ERROR creating $newdir : Perl says $!"; }

    Update ; Not sure why this is near the end of program at line 76

    mkdir("$claws_tmpdir", 0755);

    It should probably be up near line 64

    my $MAIL_dir = "$kmaildir"; unless ($PRETEND){ mkdir($claws_tmpdir, 0755) or die "ERROR creating $claws_tmpdir : Perls says $!"; }
    poj

      Thanks poj. I tried that code and got an error msg "Global symbol "$newdir" requires explicit package name". I assume that must be due to the fact that the original code has "$newdir" and the replacement is $newdir

      The root of the problem is that the script is allowing the creation of a file before that path name for _that_ file has been created.That needs to have in the subroutine "process_file", yet it seems only the filename is parsed to that subroutine, not the path name as well ??

Re: Convert KMail emails to Claws
by peterr (Scribe) on Apr 28, 2017 at 05:12 UTC

    Just ran the script again. No error messages this time, and it seems all the files have now been converted. Just need to go through and check everything. Thanks to everyone for your help.