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

I'm trying to create a whole slew of directories using:
open PUB_CAT, 'pub_cat.txt' or die "Can't open file: $!\n"; foreach (<PUB_CAT>) { mkdir "../Online_Library/$_", 777; }
PUB_CAT just contains a list of names of directories. The script worked in that these directories were created, however, all the directories were saved as 411, meaning that I don't even have access to change them or read or write to them. Also, when I look at the directories via telnet, they appear to be the file name i wanted with two extra guestion marks at the end, so that mydirectory looks like mydirectory??
1. How do I fix it so that the script creates directories as 777?
2. How do I go about deleting all these useless directories?
3. Why is it adding the two ?? at the end of the directory name?
Thanks, this perplexes me greatly and I really don't even know what's wrong...

Replies are listed 'Best First'.
Re: mkdir mode troubles
by chromatic (Archbishop) on May 15, 2001 at 02:46 UTC
    mkdir expects an octal number for the mode. You might have beter luck with 0777. More information about the mode can be found in umask.

    You can probably also get rid of the extra bits at the end of the directory names if you chomp each line of the file. I'll assume that the line ending is \r\n.

Re: mkdir mode troubles
by arturo (Vicar) on May 15, 2001 at 02:46 UTC

    The "mask" argument to perlfunc:mkdir must be an *octal number*, so that leading 0 is important (tells Perl it's an octal, not a decimal, value).

    Try it with '0777' instead and see what happens.

    If you're the owner of those directories (which you should be), change their permissions on the command line with chmod -R 0755 Online_library/*. You can also use chmod within Perl (but mind the octal numbers!).

    Finally, I'd bet the '??' goes away if you chomp each line before you feed it to mkdir.

    HTH.

    perl -e 'print "How sweet does a rose smell? "; chomp $n = <STDIN>; $r +ose = "smells sweet to degree $n"; *other_name = *rose; print "$other +_name\n"'
      The "mask" argument to perlfunc:mkdir must be an *octal number*,
      No, it must be a numeric expression. We commonly express the number as octal, because those octal numbers have mnemonic value. But if you can calculate in your head that 0777 is the same as {firing up calculator...} 511 decimal, then just type 511 there, and it works just fine.

      The problem with writing 777 there is that it's interpreted as if it was 01411, which is interpreted by Unix as sticky bit, read-only for user, execute-only for group and others. Certainly not a good permission for a new directory.

      But let's kill this meme that this second parameter "must be octal". It must be a number, and we usually write it as octal because of the mnemonic value.

      -- Randal L. Schwartz, Perl hacker

      Try it with '0777' instead and see what happens.

      Okay:

      #!/usr/bin/perl -w print 0777, $/; print 0+'0777', $/; printf "0%o\n",0777; printf "0%o\n",'0777';
      produces
      511 777 0777 01411

      Okay, so you probably didn't mean for me to type in the single quotes. But I thought this was a subtle and sometimes important point. The string '0777' is silently (no warnings) interpretted as the decimal value 777, not the octal value 0777.

              - tye (but my friends call me "Tye")
Re: mkdir mode troubles
by clintp (Curate) on May 15, 2001 at 02:50 UTC
    First, you're not chomping $_ so there's going to be trailing newlines in your directory names.

    Second, mkdir has a return value -- use it. mkdir||warn is a good place to start.

    Third, mkdir takes 777 and combines that with the value from umask to figure out the permissions on newly created directories (it's in the manual page). If you want to be certain, use chmod after creating the directory.

    Last, if (after you fix the chomp) you still have ??'s after the directory names being created try printing $_ as you're creating the directories. It may have special characters or ??'s in them.

      I did print out the $_ as I was printing, and I found that there are two non printable letters. So I did:
      open PUB_CAT, 'pub_cat.txt' or die "Can't open file: $!\n"; foreach (<PUB_CAT>) { local $/ = "\n"; chomp; local $/ = "\r"; chomp; print "(<br> $_)"; mkdir "../Online_Library/$_", 0777; }
      which works but seems ugly. Is there a better way? i.e. is there a way to test the end of a string for all common dividers?
        Instead of changing $/ and chomping, why not just say

        s/\s+$//;

        This should remove all trailing whitespace.
Re: mkdir mode troubles
by mr.nick (Chaplain) on May 15, 2001 at 02:47 UTC
    Force mkdir's second argument to be octal, as in the Unix CHMOD's representation, by prepending a 0 ala
    mkdir "../Online_Library/$_", 0777;