Linux question of the day

ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
Let's try playing this...

Question #1: Why was the echo command executed?
$ if [ false ]; then echo "That was a true statement"; fi

I will post the answer in 24 to 48 hours depending on the number of responses this thread gets...
“You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

GetCertified4Less
- discounted vouchers for certs
«1345678

Comments

  • LinuxInAlaskaLinuxInAlaska Posts: 6Member ■□□□□□□□□□
    The [] implement the test command. The test command sees false as a string not a command. Because it sees it as a string, the test command tests to see if it is non-zero length. Because it has length, the test command returns a true. Therefore the echo command is executed. You could make this work right by just leaving the brackets off.
  • LinuxInAlaskaLinuxInAlaska Posts: 6Member ■□□□□□□□□□
    Keep these questions coming. It makes for great studying.
  • lsud00dlsud00d Posts: 1,571Member
    I enjoy using the test parameters for the conditional expressions in loops, i.e.

    #!/bin/bash
    file=/path/to/file.txt

    if [ -f $file ]; then
    echo "$file exists, exiting"
    else
    echo "$file does not exist, creating"
    touch $file
    echo "$file created, exiting script"
    fi
  • paul78paul78 Posts: 2,982Member ■■■■■■■■■■
    The [] implement the test command. The test command sees false as a string not a command. Because it sees it as a string, the test command tests to see if it is non-zero length. Because it has length, the test command returns a true. Therefore the echo command is executed. You could make this work right by just leaving the brackets off.

    Interesting.. I will have to look closer. When I looked at it, I thought that it was because/bin/false returns a non-zero exit code which is evaluated to true.
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    paul78 wrote: »
    Interesting.. I will have to look closer. When I looked at it, I thought that it was because/bin/false returns a non-zero exit code which is evaluated to true.
    I was about to post the answer but now that there are different perspectives, I don't want to spoil it, let's keep the conversation going...
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • lsud00dlsud00d Posts: 1,571Member
    The expression resulted in an exit status of 0, resulting in the echo
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    paul78 wrote: »
    Interesting.. I will have to look closer. When I looked at it, I thought that it was because/bin/false returns a non-zero exit code which is evaluated to true.
    That is actually a good thought, inconsistencies between C-style and bash-style true/false can be quite messy.

    Can you prove it for this example though? What happens if you replace false with true?
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    lsud00d wrote: »
    The expression resulted in an exit status of 0, resulting in the echo
    Which expression,
    false
    
    or
    [ false ]
    
    ?

    icon_wink.gif
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • LinuxInAlaskaLinuxInAlaska Posts: 6Member ■□□□□□□□□□
    Check the "info coreutils test invocation" page, it explains what is happening in two different locations. The info page explains that if there is only one argument in the expression it will return true unless the argument is null and then it will return false. Also it says that if the argument is a string alone, it treats the test expression just like "-n String​"
  • paul78paul78 Posts: 2,982Member ■■■■■■■■■■
    Ahh. I assume then that my premise only works if command substitution was used. I.e. 'false instead of false.

    @chooselife- I would have to agree with @linuxinalaska then. To your other question about using/bin/true- that command also returns exit code of zero as I recall so the echo is not executed is command substitution was used in the expression.
  • lsud00dlsud00d Posts: 1,571Member
    ChooseLife wrote: »
    [ false ]
    

    It can be [ abc ] or [ 123 ]...because it's ([ ended by ]) aliased to test which is simply evaluating it as a string, which returns exit status 0 and executes the echo
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    paul78 wrote: »
    @chooselife- I would have to agree with @linuxinalaska then. To your other question about using/bin/true- that command also returns exit code of zero as I recall so the echo is not executed is command substitution was used in the expression.
    Yep. The other way to look at it if the 0s and 1s were reversed in this case, then
    $ if [ true ]; then echo "That was a true statement"; fi
    
    would produce the opposite result, but they both do the same
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    lsud00d wrote: »
    It can be [ abc ] or [ 123 ]...because it's ([ ended by ]) aliased to test which is simply evaluating it as a string, which returns exit status 0 and executes the echo
    You got it
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    So, the correct answer is:
    The [] implement the test command. The test command sees false as a string not a command. Because it sees it as a string, the test command tests to see if it is non-zero length. Because it has length, the test command returns a true. Therefore the echo command is executed. You could make this work right by just leaving the brackets off.
    It is so complete that I have nothing to add to it :)

    The reason for this question is that like lsud00d said, it is often used in cases like if [ -f $file ]; and so people could forget that it does not work as "if [ boolean-expr ]" but rather as "if test expression" which by default does a string evaluation.

    P.S. And like LinuxInAlaska said, this would work correctly:

    $ if false ; then echo "That was a true statement"; fi
    
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • lsud00dlsud00d Posts: 1,571Member
    Very interesting! There are so many little things about linux to remember...I find myself revisiting topics often.

    For instance, I'm still iffy on single/double quotes and ticks when using them in scripts. I get it right most of the time but I need to do better on remembering which to use when icon_study.gif
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    Ok, here's a simple one... If you certainly know the answer, let the others think about it first icon_wink.gif


    Question #2: Suppose there is a TrashCan directory that you want to empty. Why is the following approach bad? How would you fix it?
    $ cd TrashCan; rm -rf *
    
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • paul78paul78 Posts: 2,982Member ■■■■■■■■■■
    Good one.. usually, you only need to do that wrong once to realize why... icon_lol.gif
  • lsud00dlsud00d Posts: 1,571Member
    I cringe at rm -rf....never made that mistake, but mannnnn I don't think you can hose something that easily doing anything else in the world!
  • boredgameladboredgamelad Posts: 365Member ■■■■□□□□□□
    My favorite rm -rf joke is that it stands for "read mail really fast".

    I like the idea behind this thread! I am a bit of a Linux newbie so I will be checking back here often.
  • marco71marco71 Posts: 149Member
    ChooseLife wrote: »

    Question #2: Suppose there is a TrashCan directory that you want to empty. Why is the following approach bad? How would you fix it?
    $ cd TrashCan; rm -rf *
    

    Second command, rm -rf * , (because of ; separator), will always be executed, no matter if first command fails or not (for example, if TrashCan is a hidden folder, then cd TrashCan fails, shoud be cd .TrashCan)... and will erase all current folder if cd command fails :)
    correct would be to use && separator for the two commands, in this way, second command is executed only when first one returns true:
    $ cd TrashCan && rm -rf *
    
    [/QUOTE]
    An opposite to && is the || separator; in this case second command is executed only when first one fails

    EDIT:
    sorry, didnt see your first thought ... I should have let the others to think at it first
  • LinuxInAlaskaLinuxInAlaska Posts: 6Member ■□□□□□□□□□
    I agree with Marco71 on why it is a bad idea and what can go wrong. I would take a different route to perform the delete and just do
    rm -rf TrashCan/*
    

    If you fat finger the name TrashCan, it would simply come back with a "No such file or directory" error.
  • lsud00dlsud00d Posts: 1,571Member
    I'm a fan of absolute paths for stuff like this icon_wink.gif
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    Ok, so the correct answer is:
    marco71 wrote: »
    Second command, rm -rf * , (because of ; separator), will always be executed, no matter if first command fails or not (for example, if TrashCan is a hidden folder, then cd TrashCan fails, shoud be cd .TrashCan)... and will erase all current folder if cd command fails :)
    One more case where cd may fail is insufficient rights to access the target folder.
    marco71 wrote: »
    correct would be to use && separator for the two commands, in this way, second command is executed only when first one returns true:
    $ cd TrashCan && rm -rf *
    
    Absolutely. And while cd can be avoided altogether as @LinuxInAlaska suggested, this approach can be generalized to any set of chained commands. I wanted to highlight this case because of a potential habit of mis-using a semicolon when in fact the sequence of command is logically conditioned.
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    Question #3. So we established that one safe way to clean up a directory is to execute:
    $ cd TrashCan && rm -rf *
    
    Now suppose TrashCan's permissions do not allow the user access its content.
    Is there anything wrong with the following line?
    $ sudo cd TrashCan && rm -rf *
    
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • log32log32 Posts: 217Users Awaiting Email Confirmation
    Very nice thread, this is an easy one:
    what is the directory structure of this command ?
    mkdir -p myProject/{src,doc/{api,system},tools,db}
    
  • hiddenknight821hiddenknight821 Posts: 1,209Member ■■■■■□□□□□
    ChooseLife wrote: »
    Question #3. So we established that one safe way to clean up a directory is to execute:
    $ cd TrashCan && rm -rf *
    
    Now suppose TrashCan's permissions do not allow the user access its content.
    Is there anything wrong with the following line?
    $ sudo cd TrashCan && rm -rf *
    

    Without cheating, I'd say the first operator (the expression before the double ampersands) would be evaluated as true as long as the correct password is provided. Thus, the last operator would be executed. However, it will not run the `rm -rf *' command on the TrashCan/ directory. It'd be committed to the current directory instead.

    That's the best I can come up with.

    log32 wrote: »
    Very nice thread, this is an easy one:
    what is the directory structure of this command ?
    mkdir -p myProject/{src,doc/{api,system},tools,db}
    

    Oh, c'mon. Could you at least give us questions that's at the same level as ChooseLife's? His questions actually made me ponder.

    myProject/src
    myProject/doc
    myProject/doc/api
    myProject/doc/system
    myProject/tools
    myProject/db

    I didn't ****, but if I'm wrong, then there goes your proof that I didn't.
  • lsud00dlsud00d Posts: 1,571Member
    Oh, c'mon. Could you at least give us questions that's at the same level as ChooseLife's? His questions actually made me ponder.

    TBH I had to think about it. It's not very often I'm mkdir'in beyond the dir needed and it brings an element of "order of operations" a la mathematics to properly evaluate the parent switch directory creation. Same thing with recursive commands...if you don't go beyond what you're doing in that specific directory the specifics can escape you.
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    Without cheating, I'd say the first operator (the expression before the double ampersands) would be evaluated as true as long as the correct password is provided. Thus, the last operator would be executed. However, it will not run the `rm -rf *' command on the TrashCan/ directory. It'd be committed to the current directory instead.
    Good answer. It is partially correct, but does not cover the main "tricky" part of this question icon_smile.gif
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • ChooseLifeChooseLife Posts: 941Member ■■■■■■■□□□
    log32 wrote: »
    mkdir -p myProject/{src,doc/{api,system},tools,db}
    
    Ah, cool, never had to use nested sets like this, good to know they are possible


    P.S. Keep 'em coming! :)
    “You don’t become great by trying to be great. You become great by wanting to do something, and then doing it so hard that you become great in the process.” (c) xkcd #896

    GetCertified4Less
    - discounted vouchers for certs
  • hiddenknight821hiddenknight821 Posts: 1,209Member ■■■■■□□□□□
    lsud00d wrote: »
    TBH I had to think about it. It's not very often I'm mkdir'in beyond the dir needed and it brings an element of "order of operations" a la mathematics to properly evaluate the parent switch directory creation. Same thing with recursive commands...if you don't go beyond what you're doing in that specific directory the specifics can escape you.

    I do not mean to belittle the question, and I apologize if Log32 finds it offensive. I just didn't think it's as "tricky" or comparative to ChooseLife's, but to each his own, I suppose. Although, I couldn't disagree with your statement as we all tend to forget commands we don't use very often. It just happened that I've been studying Linux for quite awfully a long time since July. I recalled this recursive command from the LFS project I was doing over the summer, and it certainly helped.
    ChooseLife wrote: »
    Good answer. It is partially correct, but does not cover the main "tricky" part of this question icon_smile.gif

    Okay. The more I think about it, the trickier it gets. Since I had it partially correct, I believe the `rm -rf' command didn't even execute at all, because it requires root privilege. Beat me! icon_rolleyes.gif I might as well go ahead and **** to find out... in the VM, of course, you slick, sick, sadist. icon_lol.gif
Sign In or Register to comment.