Linux question of the day
ChooseLife
Member Posts: 941 ■■■■■■■□□□
in Linux+
Let's try playing this...
Question #1: Why was the echo command executed?
I will post the answer in 24 to 48 hours depending on the number of responses this thread gets...
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
GetCertified4Less - discounted vouchers for certs
Comments
-
LinuxInAlaska Member Posts: 6 ■□□□□□□□□□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.
-
lsud00d Member Posts: 1,571I 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 -
paul78 Member Posts: 3,016 ■■■■■■■■■■LinuxInAlaska wrote: »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. -
ChooseLife Member Posts: 941 ■■■■■■■□□□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.“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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□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.
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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□The expression resulted in an exit status of 0, resulting in the echo
false
or[ false ]
?
“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 -
LinuxInAlaska Member Posts: 6 ■□□□□□□□□□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"
-
paul78 Member Posts: 3,016 ■■■■■■■■■■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. -
lsud00d Member Posts: 1,571ChooseLife 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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□@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.
$ 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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□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 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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□So, the correct answer is:LinuxInAlaska wrote: »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.
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 -
lsud00d Member Posts: 1,571Very 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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□Ok, here's a simple one... If you certainly know the answer, let the others think about it first
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 -
paul78 Member Posts: 3,016 ■■■■■■■■■■Good one.. usually, you only need to do that wrong once to realize why...
-
lsud00d Member Posts: 1,571I 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!
-
boredgamelad Member Posts: 365 ■■■■□□□□□□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. -
marco71 Member Posts: 152 ■■■□□□□□□□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 -
LinuxInAlaska Member Posts: 6 ■□□□□□□□□□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. -
ChooseLife Member Posts: 941 ■■■■■■■□□□Ok, so the correct answer is: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 failscorrect 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 *
“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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□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 -
log32 Users Awaiting Email Confirmation Posts: 217Very nice thread, this is an easy one:
what is the directory structure of this command ?mkdir -p myProject/{src,doc/{api,system},tools,db}
-
hiddenknight821 Member Posts: 1,209 ■■■■■■□□□□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.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. -
lsud00d Member Posts: 1,571hiddenknight821 wrote: »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. -
ChooseLife Member Posts: 941 ■■■■■■■□□□hiddenknight821 wrote: »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.“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 -
ChooseLife Member Posts: 941 ■■■■■■■□□□
mkdir -p myProject/{src,doc/{api,system},tools,db}
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 -
hiddenknight821 Member Posts: 1,209 ■■■■■■□□□□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
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! I might as well go ahead and **** to find out... in the VM, of course, you slick, sick, sadist.