LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-17-2019, 04:30 PM   #1
young_jedi
Member
 
Registered: Mar 2019
Posts: 37

Rep: Reputation: Disabled
Bash '||' OR operator not working in Perl?


I'm trying to make a little Perl script to mount/umount devices on the command line.. I came up with the following
but in line 8 the '||' operator is not working (its works by itself on the command line)... BTW the scripts uses a while loop so I can keep toggling mount/umount devices.


Code:
while ( <<>> ) {
    system "clear";
    @devices=`lsblk -f | egrep -w 'mmcblk.|sd.' | awk '{print\$1" "\$3" "\$7}'`;
    foreach $index (0..$#devices) {
        print "$index: $devices[$index]";
    }
    $index = $_;
    system "udisksctl mount -b /dev/$devices[$index] > /dev/null 2>&1 || umount /dev/$devices[$index]";
    print "Enter an index number: ";
}

Last edited by young_jedi; 03-17-2019 at 05:10 PM.
 
Old 03-17-2019, 05:13 PM   #2
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Quote:
Originally Posted by young_jedi View Post
I'm trying to make a little Perl script to mount/umount devices on the command line.. I came up with the following
but in line 8 the '||' operator is not working (its works by itself on the command line)... BTW the scripts uses a while loop so I can keep toggling mount/umount devices.


Code:
while ( <<>> ) {
    system "clear";
    @devices=`lsblk -f | egrep -w 'mmcblk.|sd.' | awk '{print\$1" "\$3" "\$7}'`;
    foreach $index (0..$#devices) {
        print "$index: $devices[$index]";
    }
    $index = $_;
    system "udisksctl mount -b /dev/$devices[$index] > /dev/null 2>&1 || umount /dev/$devices[$index]";
    print "Enter an index number: ";
}
code only does what you tell it to.
I do not do perl
https://www.tutorialspoint.com/perl/...rs_example.htm
but, examine your logical condition

if true && true || false
if false || do something

the condition you're using needs to give back a status of completion or a fail of completion in order to execute any further code within that statement.

Code:
is true no echo
[[ -d /usr ]] || echo "yes"
is false because there is a /usr
it fires an echo
[[ ! -d /usr ]] || echo "no"
maybe something like this
Code:
[[$(system "udisksctl mount -b /dev/$devices[$index] > /dev/null 2>&1) ]] || umount /dev/$devices[$index]";
checks the return value within the brackets ( ) so it can act upon it.
therefore it should be written like this.
Code:
# if mounted then un-mount && , or if not mounted then mount ||
[[$(system "udisksctl mount -b /dev/$devices[$index] > /dev/null 2>&1) ]] &&
umount /dev/$devices[$index]" ||
mount /dev/$devices[$index]";
but written in perl script, not bash. Though I am not sure in perl if that is a true ternary operator in perl either.
this is better sutied for your perl script
The ternary operator in Perl

Last edited by BW-userx; 03-17-2019 at 05:36 PM.
 
Old 03-17-2019, 08:08 PM   #3
young_jedi
Member
 
Registered: Mar 2019
Posts: 37

Original Poster
Rep: Reputation: Disabled
Thanks for replying, Perl is a glue programming language so it should execute bash code natively (I don't have to do what you're saying in a bash script). But I see what you're saying about surrounding it in brackets to capture the return status and having that factor in on whether the next command should run or not. Ill check to see how to do that in Perl and if that works, thank you..

Last edited by young_jedi; 03-17-2019 at 08:11 PM.
 
Old 03-17-2019, 11:02 PM   #4
scasey
LQ Veteran
 
Registered: Feb 2013
Location: Tucson, AZ, USA
Distribution: CentOS 7.9.2009
Posts: 5,723

Rep: Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211Reputation: 2211
The syntax for the system call is
Code:
system()
see this
Note that the default shell for the system() in Unix is sh -c -- not sure what the default is for Linux. Might be bash, but you'd need to check.

Last edited by scasey; 03-17-2019 at 11:04 PM.
 
Old 03-19-2019, 05:00 PM   #5
rnturn
Senior Member
 
Registered: Jan 2003
Location: Illinois (SW Chicago 'burbs)
Distribution: openSUSE, Raspbian, Slackware. Previous: MacOS, Red Hat, Coherent, Consensys SVR4.2, Tru64, Solaris
Posts: 2,799

Rep: Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550Reputation: 550
Quote:
Originally Posted by young_jedi View Post
Thanks for replying, Perl is a glue programming language so it should execute bash code natively (I don't have to do what you're saying in a bash script). But I see what you're saying about surrounding it in brackets to capture the return status and having that factor in on whether the next command should run or not. Ill check to see how to do that in Perl and if that works, thank you..
Check the "perlfunc" manpage for the "system()" call. I think what you're attempting to do in a single system() call may need to be split into two calls. The example on that page:
Code:
@args = ( "command", "arg1", "arg2", ... )
system( @args ) == 0
    || die "system @args failed: $?"
might be adapted to what you're trying to do:
Code:
$mount_cmd = "udisksctl mount -b /dev/$devices[$index] > /dev/null 2>&1";
$umount_cmd = "umount /dev/$devices[$index]";
system( $mount_cmd ) == 0
    || system( $umount_cmd );
Worth a try.

HTH...

Cheers.
 
1 members found this post helpful.
Old 03-19-2019, 06:40 PM   #6
young_jedi
Member
 
Registered: Mar 2019
Posts: 37

Original Poster
Rep: Reputation: Disabled
@scasey, You can omit the parens as long as it doesnt change the meaning of the code.

@rnturn, Thats I good idea I'll try braking it up into variables, and if that doesnt work ill try two system calls thanks.. Im trying to write elegant code....

Last edited by young_jedi; 03-19-2019 at 06:45 PM.
 
Old 03-20-2019, 08:39 PM   #7
young_jedi
Member
 
Registered: Mar 2019
Posts: 37

Original Poster
Rep: Reputation: Disabled
@rnturn thanks it works now though I cant get >/dev/null 2>&1 to work for the same reason... But besides that it all works perfectly..

Code:
This is free software..

#!/usr/bin/perl
$simulate_return='xdotool key Return ; xdotool key Return';
system $simulate_return;

while ( <> ) {
    system 'clear';

    @devices=`lsblk -f | egrep -w 'mmcblk.|sd.' | awk '{print\$1" "\$3" "\$7}'`;
    foreach $index (0..$#devices) {
        print "$index: $devices[$index]";
    }

    print "\n", 'Choose an index number: ';
    $selected = <>;
    system $simulate_return;
    
    $mount="udisksctl mount -b /dev/$devices[$selected]";
    $umount="udisksctl unmount -b /dev/$devices[$selected]";
    system( $mount ) == 0 || system( $umount );
}
I'm marking this thread as solved, but if anyone knows how I cant get the '>/dev/null 2>&1' part to work that will be great! I even tried using the long form, e.g.:
Code:
$mount="udisksctl mount -b /dev/$devices[$selected] >/dev/null 2>&1";
$umount="udisksctl unmount -b /dev/$devices[$selected]";
unless ( !system $mount ) {       
    system $umount;
}

Last edited by young_jedi; 03-21-2019 at 11:18 PM.
 
Old 03-20-2019, 10:09 PM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,856
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
What is the 'short form'? What "doesn't work" actually means?
 
Old 03-21-2019, 11:13 PM   #9
young_jedi
Member
 
Registered: Mar 2019
Posts: 37

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by NevemTeve View Post
What is the 'short form'? What "doesn't work" actually means?
This is the short-syntax:

Code:
$mount="udisksctl mount -b /dev/$devices[$selected] >/dev/null 2>&1";
$umount="udisksctl unmount -b /dev/$devices[$selected]";
system( $mount ) == 0 || system( $umount );
Basically im using bash's OR '||' operator to toggle between mount/umount.. If the device is already mounted
then it will unmount it, but in the process the mount command will return in error.. I want to "hide" that error
by redirecting STDERR to /dev/null.. But its not working.. If you notice in my working code above I removed
'>/dev/null 2>&1' cause it broke the script..

Last edited by young_jedi; 03-21-2019 at 11:16 PM.
 
Old 03-22-2019, 10:50 AM   #10
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,856
Blog Entries: 1

Rep: Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869Reputation: 1869
Try this in shell:
Code:
true  >/dev/null 2>&1 || echo "true(1) gave error"
false >/dev/null 2>&1 || echo "false(1) gave error"
result:
Code:
false(1) gave error
Try this in perl:
Code:
#!/usr/bin/perl -w

use strict;

system ('false >/dev/null 2>&1') == 0 || system ('echo "false(1) gave error"');
system ('true  >/dev/null 2>&1') == 0 || system ('echo "true(1) gave error"');
result:
Code:
false(1) gave error
Note: there is a well known problem here: in shell 0=success, other=errorcode; in C/Perl/etc 0=false, 1=true.
(It would be less problematic, if false(1) would be called fail(1), and true(1) would be called success(1).)

Last edited by NevemTeve; 03-22-2019 at 10:55 AM.
 
2 members found this post helpful.
Old 03-23-2019, 07:20 PM   #11
young_jedi
Member
 
Registered: Mar 2019
Posts: 37

Original Poster
Rep: Reputation: Disabled
So you're saying the nonzero return values are actually true (backwords from the traditional "0 but true" notion that the shell uses). If that's the case than all I should have to do is remove the negation (!) operator, but somehow I don't think that's going to work... Cause i'm pretty sure I tried that already, but i'll try it again.. But rather what if the bash command is giving a nonzero exit status that actually indicates success (as they can return whatever their programmed to), is that a possability? Anyway thanks for bringing that to my attention, I didn't know that until now.

Last edited by young_jedi; 03-23-2019 at 07:22 PM.
 
Old 03-25-2019, 04:42 AM   #12
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
well, for a kick-off you are doing the redirections in the wrong order:

Code:
>/dev/null  # stdout to null
2>&1        # stderr to stdout (i.e. null!)
 
Old 03-25-2019, 05:25 AM   #13
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
you don't use awk etc from Perl,

take a look at what Perl can really do:
using the -J switch on lsblk
(You may find it interesting, or not)

Code:
use strict;
use Data::Dumper;
use JSON;

my $x =  from_json qx#lsblk -fJ#;

warn Dumper($x);

foreach my $disk ( @{$x->{blockdevices}} ) {

        # warn Dumper \$disk;
        foreach my $slice ( @{$disk->{children}} ) {

                while ( my ($k, $v) = each %{$slice}) {
                        print "$k = $v\n";
                }
        }
}
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Equivalent to Perl's "=~" Operator? mrm5102 Programming 3 07-25-2012 08:21 AM
Bash problem : -bash: [: /bin/bash: unary operator expected J.A.X Linux - Software 1 09-22-2011 05:52 AM
[SOLVED] C++ Operator Overloading Within an Already Overloaded Operator mirlin510 Programming 8 04-17-2011 12:02 PM
Help With Java Problem Please"""""""""""" suemcholan Linux - Newbie 1 04-02-2008 06:02 PM
Perl question concerning the "next" operator joesbox Programming 3 03-27-2005 08:59 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:07 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration