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

Hi Monks!
I have a subroutine which gets a path to a script and content, creates the file and adds the content into the script. The code:
sub create_script { my ($script_path,$content) = @_; open(my $fh, '>', "$script_path") or die "Could not open script"; print $fh "set -x\n"; print $fh $content; close($fh); }
It's a bash script and I need to give it exec permissions, the same result as I get from chmod a+x script.sh. I could not figure a straightforward way to do this but I might miss it. For example, you can't pass it to the open sub. Also I came across with chmod but you need to pass a value (like 0777), instead of a+x and as I understand, it's not the same thing. Furthermore, I could just do `chmod a+x script.sh` right after creating the file, but I prefer a more of a perl-way. Is it possible to suggest a way?

Replies are listed 'Best First'.
Re: Chmod a+x a file in Perl
by choroba (Cardinal) on Feb 15, 2022 at 19:10 UTC
    File::chmod supports symbolic modes, too.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Chmod a+x a file in Perl
by atcroft (Abbot) on Feb 16, 2022 at 00:45 UTC

    *Nix permissions are based around 3 categories (user, group, and other) and 3 values (read, write, and execute). A value such as 0777 the octal (base-8) value that represents giving each category each of the permissions. The value '7' isn't being "lucky" here-it is the sum of the three bits used to represent the values. The actual meaning of each bit in the value is:
    \ReadWriteExecuteTranslation ('rwx')
    0000---
    1001--x
    2010-w-
    3011-wx
    4100r--
    5101r-x
    6110rw-
    7111rwx

    Now take those values and apply by user to your example of 0777:
    \UserGroupOther
    Read444
    Write222
    Execute111
    Total777
    Needless to say, giving anyone and everyone read, write, and execute permissions to a file is a BAD IDEA. (If there was ever a place where the old HTML blink tag might be approrpriate, it was the end of the previous sentence.)

    To do the equivalent of 'a+x' you would need to get the current permissions (via stat) and OR ('|') that value with 0111. For each category of user, this gives you the following permissions:
    A (rwx)BA|B (rwx)
    0 (---)11 (--x)
    1 (--x)11 (--x)
    2 (-w-)13 (-wx)
    3 (-wx)13 (-wx)
    4 (r--)15 (r-x)
    5 (r-x)15 (r-x)
    6 (rw-)17 (rwx)
    7 (rwx)17 (rwx)

    Hope that helps.

      If you want to see all 4096 possible file permissions, the following code will generate each of them in the directory of your choice (named '0nnnn_xxxxxxxxx.txt', where '0nnnn' is the octal permission, and 'xxxxxxxxx' is the string form of the permissions). (Each file contains only the text of its file name, including the provided path.)

      Code:

      Example of created files:

      $ ./working --create_dir --target_dir my_foo $ cd my_foo && ls -labhrt | tail -n 1000 | head -n 10 ---S-ws--x 1 User Group 27 Feb 17 23:29 06031_--S-ws--x.txt ---S-ws-w- 1 User Group 27 Feb 17 23:29 06032_--S-ws-w-.txt ---S-ws-wx 1 User Group 27 Feb 17 23:29 06033_--S-ws-wx.txt ---S-wsr-- 1 User Group 27 Feb 17 23:29 06034_--S-wsr--.txt ---S-wsr-x 1 User Group 27 Feb 17 23:29 06035_--S-wsr-x.txt ---S-wsrw- 1 User Group 27 Feb 17 23:29 06036_--S-wsrw-.txt ---S-wsrwx 1 User Group 27 Feb 17 23:29 06037_--S-wsrwx.txt ---Sr-S--- 1 User Group 27 Feb 17 23:29 06040_--Sr-S---.txt ---Sr-S--x 1 User Group 27 Feb 17 23:29 06041_--Sr-S--x.txt ---Sr-S-w- 1 User Group 27 Feb 17 23:29 06042_--Sr-S-w-.txt

      Example of --debug output (d3106 = 06042):

      $ ./working --create_dir --target_dir my_foo --debug # ---skip--- %perm = ( "octal" => { "0_special" => 3072, "1_user" => 0, "2_group" => 32, "3_other" => 2 }, "octal_value" => { "0_special" => 6, "1_user" => 0, "2_group" => 4, "3_other" => 2 }, "raw_octal" => 3106, "str" => { "1_user" => "--S", "2_group" => "r-S", "3_other" => "-w-" } ); # ---skip---
Re: Chmod a+x a file in Perl
by Anonymous Monk on Feb 16, 2022 at 17:53 UTC

    It would be nice if there were a Perl module that took a chmod(1) mode string and set the file mode from it. But I can't find one. The nearest I can find is File::Mode, which was last updated in 2000, though it does pass tests on modern Perls. It requires a full mode specification (i.e. rwxr--r--, not a+x), has a strange (to me) interface, and only does the string-to-octal conversion.

    I know this is not very helpful, but I'm hoping if I post a response pleading ignorance someone will comment "No, you're wrong. <insert_module_name_here> does exactly what you want."

      I know this is not very helpful, but I'm hoping if I post a response pleading ignorance someone will comment "No, you're wrong. <insert_module_name_here> does exactly what you want."

      You didn't read the thread.

        Not the critical line, anyway. Thanks.