[opensuse] question on if clause formatting
I am trying to set up ssh, and I find different command line examples on the internet to help in my research. As I am learning CLI and scripting, can someone explain the following to me please? In a given directory, I typed in the following line. if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi It created the file authorized_keys and gave it the time stamp and changed the permission. I got that part. The only thing I don't understand is the very first boolean clause after the "if". What exactly does the exclamation mark signify? What also is the "-f" option? Thanks George -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/10/2011 10:25 AM, George OLson wrote:
I am trying to set up ssh, and I find different command line examples on the internet to help in my research. As I am learning CLI and scripting, can someone explain the following to me please?
In a given directory, I typed in the following line.
if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi
It created the file authorized_keys and gave it the time stamp and changed the permission. I got that part.
The only thing I don't understand is the very first boolean clause after the "if".
What exactly does the exclamation mark signify?
What also is the "-f" option?
Thanks George
http://www.linuxtutorialblog.com/post/tutorial-conditions-in-bash-scripting-... is one of the many places you'll be directed to if you use an appropriate google search. -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
Ed Greshko said the following on 11/09/2011 09:35 PM:
http://www.linuxtutorialblog.com/post/tutorial-conditions-in-bash-scripting-...
Neat! I like having the tables of values. That gets cut-and-pasted into my book of cheat-sheets. If I had a tablet I'd put the book of cheat sheets in that :-)
is one of the many places you'll be directed to if you use an appropriate google search.
google for "[" ? -- In cyberspace no-one can hear you scream - BUT EVERYONE CAN SEE YOU SHOUT. -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/10/2011 10:45 AM, Anton Aylward wrote:
is one of the many places you'll be directed to if you use an appropriate google search. google for "[" ?
google for "bash if statement" -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
Hello, On Thu, 10 Nov 2011, Ed Greshko wrote:
On 11/10/2011 10:25 AM, George OLson wrote:
I am trying to set up ssh, and I find different command line examples on the internet to help in my research. As I am learning CLI and scripting, can someone explain the following to me please?
In a given directory, I typed in the following line.
if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi
It created the file authorized_keys and gave it the time stamp and changed the permission. I got that part.
The only thing I don't understand is the very first boolean clause after the "if".
What exactly does the exclamation mark signify?
What also is the "-f" option?
http://www.linuxtutorialblog.com/post/tutorial-conditions-in-bash-scripting-...
is one of the many places you'll be directed to if you use an appropriate google search.
That stuff is _SO_ WRONG! The syntax is: if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi Note: COMMANDS. Not(!) EXPRESSION. 'if [ .. ]; then' is just a weird way to write 'if /usr/bin/[ ... ]; then' or 'if builtin [ ... ]; then' which both are weird variants of '/bin/test' / 'builtin test' with the extra quirk to gobble up ']' as the last argument. And it's only an argument if it's seperated from the rest by a space etc., or else a ] will be part of the argument before it. In short: NEVER EVER EVER use [ .. ]. Use 'test'. The EXPRESSION comes with 'test': $ help test test: test [expr] Evaluate conditional expression. [..] -f FILE True if file exists and is a regular file. [..] ! EXPR True if expr is false. OTOH: [[ ... ]], (( ... )), $( ... ), $(( ... )), $[ .. ], _are_ bash syntax and NOT to be confused with [ .. ]. $ help [[ [[ ... ]]: [[ expression ]] Execute conditional command. $ help '((' (( ... )): (( expression )) Evaluate arithmetic expression. ==== man bash ==== Arithmetic Expansion $((expression)) ==== -dnh, too tired now to elaborate properly. -- "Cynical" is a term invented by optimists to describe realists. -- Gregory Benford -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/10/2011 01:39 PM, David Haller wrote:
The syntax is:
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
Note: COMMANDS. Not(!) EXPRESSION.
Ah, ok. that makes sense, why it is better to use 'test' instead of [ .. ] Ok, next question. In the script I am writing, I want to take an input, which is supposed to be a number between 1 and 15. However, if the operator enters text instead of a number, I want to find it, rather than letting the interpreter give me an error when it tries compare a string with a number. Here is my set of commands: echo "Please enter a number between 1 and 15" read entry if [ "$entry" -ge "1" -a "$entry" -le "15" ]; then count=$entry entry=$((entry +1)) else if [ "$entry" -eq "0" ]; then count=1 entry=16 else echo "invalid entry" exit fi fi I could not find a test option that would do something like the following after my read entry line and before the initial if statement: if [[ $entry not an integer ]]; then ... In reading through man bash, I couldn't find an expression that will do what I want there either. Any suggestions? George -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/10/2011 7:58 PM, George OLson wrote:
On 11/10/2011 01:39 PM, David Haller wrote:
The syntax is:
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
Note: COMMANDS. Not(!) EXPRESSION.
Ah, ok. that makes sense, why it is better to use 'test' instead of [ .. ]
Ok, next question. In the script I am writing, I want to take an input, which is supposed to be a number between 1 and 15. However, if the operator enters text instead of a number, I want to find it, rather than letting the interpreter give me an error when it tries compare a string with a number.
Here is my set of commands:
echo "Please enter a number between 1 and 15" read entry if [ "$entry" -ge "1" -a "$entry" -le "15" ]; then count=$entry entry=$((entry +1)) else if [ "$entry" -eq "0" ]; then count=1 entry=16 else echo "invalid entry" exit fi fi
I could not find a test option that would do something like the following after my read entry line and before the initial if statement: if [[ $entry not an integer ]]; then ...
In reading through man bash, I couldn't find an expression that will do what I want there either.
Any suggestions?
George
Typeset -i n read "n?Enter a number from 1 to 15: " [[ $n -ge 1 -a $n -le 15 ]] || { echo Invalid ; exit 1 ; } If you needed to allow a legitimate intentional 0 value and treat that differently from an invalid entry that got turned into a 0, then it's a few more lines to test that specially but luckily your example starts at 1 so it's easy to take advantage of the typeset integer feature. -- bkw -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
George OLson said the following on 11/10/2011 07:58 PM:
Ah, ok. that makes sense, why it is better to use 'test' instead of [ .. ]
1. Personal choice 2. Readability 3. Clarity "Clarity" because while it is clear to some of us GreyBeards it obviously wasn't clear to you, which is why this thread started. -- For every person who wants to teach there are approximately thirty people who don't want to learn--much. W. C. Sellar and R. J. Yeatman, And Now All This (1932) introduction -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/10/2011 8:29 PM, Anton Aylward wrote:
George OLson said the following on 11/10/2011 07:58 PM:
Ah, ok. that makes sense, why it is better to use 'test' instead of [ .. ]
1. Personal choice 2. Readability 3. Clarity
"Clarity" because while it is clear to some of us GreyBeards it obviously wasn't clear to you, which is why this thread started.
Pff, that's what comments are for. ;) I don't like typing. (haha no really, or maybe just run out of keystrokes after long mail list posts.) I say, if you can't read the code, you by definition aren't qualified to be monkeying with it, since I may use dense syntax but things will be organized pretty well and commented where necessary and built to be as future adjustable as possible. I will generally put the most likely adjustable stuff into variables at the top, with a nice comment if it's not completely self explanatory, that anyone can figure out and change without breaking it. Anyone else, if they are fit to monkey with it at all, then they will find the main parts organized well enough into functions and/or logical blocks or sections with just the necessary comments to explain things that aren't necessarily auto-apparent by the code itself. And the use of denser syntax will not matter at all. As a reader of others scripts, I know I don't usually value their "clarity" ;) Even the portability argument doesn't really matter any more. Even a Xenix box from 1992 had ksh88 built-in stock and that was pretty good, and even my oldest still running SCO Open Server box has ksh93, bash, and zsh as add-ons and has ksh88 built-in stock. I do have a tendency to use short cryptic variable names a bit too often though. A script full of single letter variables is certainly small and fast-looking, but can be a little hard to figure out a few years later. I generally try not to have to care later, make it a good robust black box that you won't have to go work on later. -- bkw -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
Brian K. White said the following on 11/10/2011 09:12 PM:
I say, if you can't read the code, you by definition aren't qualified to be monkeying with it,
Greybeards can read code and monkey with it. Its one of the qualifications of a Greybeard. The use of "if [" rather than "if test" is clear to a Greybeard. If fact Real Greybeards don't need the "if": [ ! -f $FILE ] && { .... } In fact BaldingGreybeards write one-line perl and sed scripts. So there! :-) -- Parents complain that "kids don't do anything for themselves anymore." Then they write letters to the board demanding that the schools do something about it. -- Arnold Lapiner -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/10/2011 9:34 PM, Anton Aylward wrote:
Brian K. White said the following on 11/10/2011 09:12 PM:
I say, if you can't read the code, you by definition aren't qualified to be monkeying with it,
Greybeards can read code and monkey with it. Its one of the qualifications of a Greybeard.
The use of "if [" rather than "if test" is clear to a Greybeard. If fact Real Greybeards don't need the "if":
[ ! -f $FILE ]&& { .... }
What's with that newbie wasteful "useles use of cat" award winning "!" in there? hehe :) Indeed my scripts are full of [[ -f $file ]] || { ... } as per my example earlier. I have confused people a few times though, ever since I got burned once, a real greybeard who is no longer with us enlightened me, I now know enough to insert a ":" in some cases to ensure that a block ends with a true if the last command in it might ever possibly not exit 0 The example: condition && { some stuff } || { other stuff } One day both some stuff AND other stuff ran. Crap that's a disaster what the hell is going on... I hate to admit but I did not figure it out myself, a wise old ksh and awk craftsman named Bob Stockler enlightened me that if the last thing in the && block doesn't happen to exit 0, then the || block gets invoked since it comes after that point and by the time the || is reached, the current error level is > 0 , which is what the || is looking for, so it runs it's following command(s) So to ensure the two sections behave as you intended, whichever block is first, make sure it ends in such a way that the first block will not itself trigger the next block. Or another way to say it, make sure the first block exits the same way as the condition that got you into that block. Only a worry if you even have any further blocks you might fall into. You don't have to worry about how the last block ends, which means you don't have to worry about the first block either if there is only one. It works (and breaks) both ways, whether you put the && first or the || first, but for at least one reason I'll show later, it's more convenient to put the && first most of the time. So, either of these is robust. condition && { did work stuff : } || { did not work stuff } or condition || { did not work stuff false } && { did work stuff } I usually have the && first, and I usually use a : instead the word true, so I have a fair scattering of single ":" just sitting out there at the ends of sections looking mysterious and pointless to people. echo statements and variable assignments always exit true, so for 90% of conditional code like this, it's unnecessary if the && is first. condition && MODE=worked || MODE=failed is good and reliable and readable although MODE=failed condition && MODE=worked is even more reliable and I use WORKED=false condition && WORKED=true whenever I can because it's more convenient to write a bunch of different times: $WORKED && some stuff... than [[ "_$MODE" = "_worked" ]] && some stuff... -- bkw -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
George OLson said the following on 11/09/2011 09:25 PM:
I am trying to set up ssh, and I find different command line examples on the internet to help in my research. As I am learning CLI and scripting, can someone explain the following to me please?
In a given directory, I typed in the following line.
if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi
It created the file authorized_keys and gave it the time stamp and changed the permission. I got that part.
The only thing I don't understand is the very first boolean clause after the "if".
What exactly does the exclamation mark signify?
MAN(1) Test says ! EXPRESSION EXPRESSION is false and -f FILE FILE exists and is a regular file Why "test"? Well at the start of the man page it also says SYNOPSIS test EXPRESSION test [ EXPRESSION ] How did I get there? Well the man page for the BASH shell says CONDITIONAL EXPRESSIONS Conditional expressions are used by the [[ compound command and the test and [ builtin commands to test file attributes and perform string and arithmetic comparisons. Expressions are formed from the following unary or binary primaries. And it goes to repeat what you can find in the TEST man page. Its nice to have TEST as a shell built in. When we got that it really improved performance over the old Bourne shell which had to fork off a process to do the test.
What also is the "-f" option?
WTF? Knowing the right man page is useful. Of course I cheat, I use 'apropos' a few times and don't expect to get the right answer the first time. -- In preparing for battle I have always found that plans are useless, but planning is indispensable. Dwight D. Eisenhower -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/10/2011 10:41 AM, Anton Aylward wrote:
George OLson said the following on 11/09/2011 09:25 PM:
I am trying to set up ssh, and I find different command line examples on the internet to help in my research. As I am learning CLI and scripting, can someone explain the following to me please?
In a given directory, I typed in the following line.
if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi
It created the file authorized_keys and gave it the time stamp and changed the permission. I got that part.
The only thing I don't understand is the very first boolean clause after the "if".
What exactly does the exclamation mark signify?
MAN(1) Test says
! EXPRESSION EXPRESSION is false
Ah, ok, so the exclamation is just like saying "not" Found the other info I needed also. Thanks for the help. George
-- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
On 11/9/2011 9:25 PM, George OLson wrote:
I am trying to set up ssh, and I find different command line examples on the internet to help in my research. As I am learning CLI and scripting, can someone explain the following to me please?
In a given directory, I typed in the following line.
if [ ! -f authorized_keys ]; then touch authorized_keys ; chmod 600 authorized_keys ; fi
It created the file authorized_keys and gave it the time stamp and changed the permission. I got that part.
The only thing I don't understand is the very first boolean clause after the "if".
What exactly does the exclamation mark signify?
What also is the "-f" option?
You want to read "man bash" top to bottom. Don't try to remember it. You'll refer to it often forever. Most of this question is under "CONDITIONAL EXPRESSIONS" A basic form of conditional logic is to test the exit value of a program. if/then/else uses this. You can say: if myprogram arguments... then echo "it worked" fi it will run myprogram arguments... and it will only do the echo it worked if myprogram exited with exit value 0. Next sometimes you want to test a condition other than the result of running myprogram. You want to say, test if $A is greater than $B The simple original answer for that way back when was just to make a program called "test" which could perform various tests for you and then it would exit with an appropriate exit value So instead of "myprogram" the very same conditional feature is just running "test" and the arguments are your desired test and everything else works the same. So you can say: if test $A -gt $B then echo "A=$A is greater than B=$B" fi Next, [ ... ] is another syntax for the test command Way back there actually was a /bin/[ but now it's built in to the shell. Among the many tests test can perform, "-f something" means "is something a regular file". It's a way to test if a file exists, and more specifically, is it a regular file and not a directory, symlink, device node, fifo, etc. The ! means to negate the value of the following test. So instead of being true if the file exists and is a regular file, it will only be true if the file does not exist, or is not a regular file. Then, if that (inversed) test is true, then create a new empty authorized_keys. They might be checking specifically for a regular file to guard aganst possible sneaky symlink tricks where maybe someone could replace an authorized keys file with a symlink to one of their own, but most likely it's just intended to make sure that the file is not a directory since that could possibly exist, but would be usable, you couldn't add a new line of text to it for example. I personally would say instead: [ -f authorized_keys ] || { rm -rf authorized_keys touch authorized_keys chmod 600 authorized_keys } This says if authorized_keys exists and is a regular file, ELSE, do the stuff in between { } && is short for then and || is short for else, and using that syntax you don't need if or fi The reason for the rm -rf is to handle the case where something named authorized_keys existed, but wasn't a plain file. You need to remove it before you can place the plain file in it's place, and if it's a directory you need to remove anything that might be in and under it too, (the -r) and most of the time when the test fails and this code is run, it will be because nothing exists not that something other than a plain file exists, so the -f just prevents rm from complaining when you ask it to remove something that wasn't there, and of course makes it delete things without asking the user if they're sure. Then create, then set perms. -- bkw -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
Brian K. White said the following on 11/09/2011 10:35 PM:
You want to read "man bash" top to bottom. Don't try to remember it.
+1
You'll refer to it often forever.
+1
Way back there actually was a /bin/[ but now it's built in to the shell.
+1 to that since it makes a big performance difference. -- He who stops being better stops being good. - Oliver Cromwell -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org To contact the owner, e-mail: opensuse+owner@opensuse.org
participants (5)
-
Anton Aylward
-
Brian K. White
-
David Haller
-
Ed Greshko
-
George OLson