I have recently met a man online that works for a fortune 500 company running a linux server. He once joked about looking for cheap help, and i jumped at the chance to offer my services. Afte a lot of talking on skype, he decided to help me learn the tricks of the trade, and possibly work for him one day. For starters i have to install a new linux kernal and learn bash. Does anyone have a good tutorial for learnin bash?
"fortune 500" is a lovely way to legitimize an otherwise unknown company's rep
Get in touch with Catherine/_player, she knows a lot about bash.
This is by far the best tutorial (well, I guess it could be considered to be more of a reference guide) for Bash that I have ever found:

http://tldp.org/LDP/abs/html/
comic, or more specifically, point Catherine at this thread. Smile It's a scripting language, so you have loops, functions, variables, and all those good things, but instead of system calls you have commands, just like the ones you might type at a bash prompt.
JoeYoung wrote:
"fortune 500" is a lovely way to legitimize an otherwise unknown company's rep
Please try to keep your posts on topic and constructive. If you have nothing worthwhile to contribute to the topic, don't contribute.

Aes wrote:
Does anyone have a good tutorial for learnin bash?
I never used a tutorial straight through, but there are plenty of great resources floating around. I suggest diving in to it and making simple scripts at first. Move files around, print stuff to the screen, stuff like that. Those are always good starting points. If I find anything specific, I'll make sure to point it your way. Keep in mind that "man" will be a very helpful tool in learning what everything does.
merthsoft wrote:
JoeYoung wrote:
"fortune 500" is a lovely way to legitimize an otherwise unknown company's rep
Please try to keep your posts on topic and constructive. If you have nothing worthwhile to contribute to the topic, don't contribute.


Actually, that's exactly what I thought. Do some background on your guy and make sure he is what he claims to be, so you don't get screwed over.
you should also make sure that you're well versed with awk and grep. both will be immensely useful to you if you ever have to work with text files.
oh I will. Trust me, I thought of that. I did some background research, and I am still doing some. So far he checks out. I wont work for him until I get his credentials, but it cant hurt to learn from him right?
elfprince13 wrote:
merthsoft wrote:
JoeYoung wrote:
"fortune 500" is a lovely way to legitimize an otherwise unknown company's rep
Please try to keep your posts on topic and constructive. If you have nothing worthwhile to contribute to the topic, don't contribute.


Actually, that's exactly what I thought. Do some background on your guy and make sure he is what he claims to be, so you don't get screwed over.

+1 this.
Yay, Bash! <3 The best way, I'd think, to learn Bash is to simply force yourself to use the command line for everything. That's mainly how I started learning, and then got hooked on, it. The parts you'd need to know, for sure, are: for loops, while loops, the `test' program ("[" and "]"), functions and passing arguments, when to quote things, and the Bash string replacement functions. As well as, of course, how to use variables.

For loops, in Bash, are different from other languages. Instead of having there be a "list" of values, separated by commas, or a for(init; condition; increment) syntax (though one exists), it loops over a "list" separated by spaces, newlines, and tabs. The typical example of a For loop that mimics C's loop is:
Code:
for i in `seq 0 9`; do
  echo $i
done
This will print out the numbers from 0 to 9 (ie, 0, 1, 2 ... 8, 9). Unfortunately, this promotes that people do things to create their own "foreach" style of loop, as well as telling them that Bash makes it harder to do what you really want (And, that awful backtick syntax). However, because Bash uses whitespace to separate each element, you can abuse that to print out, for instance, several colors in a concise manner:
Code:
for color in red white blue green yellow purple pink white black; do
  echo $color
done
This can also be used to print based on the output of another program, like, for instance, looping through each file in a directory:
Code:
for f in $(ls); do
  if [ -f $f ]; then
    echo "$f is a file"
  else
    echo "$f is not a file (Directory?)"
  fi
done


While loops are important in their own way (Although, to be honest, I rarely use them except for a "while true" loop). The important parts of a While loop match up with the important parts of an If statement. Namely: the condition for an If/While if the return value from a program. This is important because, otherwise, people do things like this:

Code:
someprogram with some args
if [ "$?" = 0 ]; then
  echo "Program succeeded!"
else
  echo "Program failed!"
fi
instead of the more succinctly as:
Code:
if someprogram with some args; then
  echo "Success"
else
  echo "Failure"
fi
Another important thing to remember is that a return value of 0 is considered "true" whereas a return value of anything but 0 is "false" and indicates a failure somewhere.

The `test' program is very important because it lets you access all the information about a file and lets you test against strings and numbers. It is typically written using the [ and ] characters, because it's easier to read. As an overview of all the things you can test against, there's this page. The more important things you can do with it are: test if a string is empty or has something in it, test if two strings are equal, check if something is a file or a directory, and negating those tests.

Code:
if [ -z "$maybe_empty" ]; then
  echo "Empty"
else
  echo "Has some content"
fi

if [ -n "$maybe_empty" ]; then
  echo "Has some content"
else
  echo "Empty"
fi

if [ "$var1" = "$var2" ]; then
  echo "The same"
else
  echo "different"
fi

if [ -f "$somefilename" ]; then
  echo "Is a file"
else
  echo "Is not a file"
fi

if [ -d "$somedirectoryname" ]; then
  echo "Is a directory"
else
  echo "Is not a directory"
fi

if [ ! "$var1" = "$var2" ]; then
  echo "Different"
else
  echo "Same"
fi
The last one can be rewritten as: if [ "$var1" != "$var2" ]. But, that is a matter of style (I prefer it at the beginning). Also, if you can insure that $var1 and $var2 will not have any spaces, you can remove the quotes. That goes for any of the test operations (And any times that you are passing arguments that are in variables). The exceptions, for `test', are the -n and -z operators. You always have to quote those, in case they end up being empty (And then Bash will not see them as real arguments).

Functions and their arguments are important to understand because, well, that's all that Bash is. The difference between a full program and a function is, simply, a function only exists inside of the current file (With the exception of the `source' program), and a program can exist anywhere in your path, and has to be marked as executable. To create a function in Bash, you can use two different methods (or three if you combine the two, as I do):

Code:
function foobar {
  # body here
}

foobar() {
  # body here
}

function foobar() {
  # body here
}
All of these code segments are exactly the same, in terms of functionality, so it all comes down to personal style (I use the latter because it makes it very easy to tell that it is a function). After you define your function, you can call it as if it is a normal program, like `sed' or `cat'. Passing arguments is, of course, the exact same, also. Inside of your function, to retrieve those arguments, you use the $1, $2, $3, etc variables. You will also have to make sure that you remember to check if all your arguments are actually passed and are valid. For instance, here is a function that, if you pass it two non-empty arguments, it prints them both out, and if you only pass one, it prints the first 3 characters from it, and if you don't pass any, it just prints an error message:
Code:
function foobar() {
  if [ -n "$1" ]; then
    if [ -n "$2" ]; then
      echo "$1 $2"
    else
      echo ${1:0:3} # this uses string manipulation functions
    fi
  else
    echo "Error: you must pass at least one argument" >&2  # &2 is shorthand for /dev/stderr
    exit
  fi
}
I mentioned, earlier, that if you are certain that a variable will not have any spaces or newlines, that you can just leave off the quotation marks completely. This applies here, as well. Typically, in my own programs, if I have some functions that I will only ever call correctly, and with variables that I know are valid, then I can leave off most of the quotes. When you have to start worrying about quotation marks is when you don't know for sure what someone else will pass your function. It's important to understand that, in Bash, the separator for arguments, and really, everything, is whitespace (like, newlines, spaces, and tabs). And, when you put double quotes (") around a variable, you tell Bash "Hey, this is all one argument" instead of saying "Here's some stuff... try to figure it out yourself". That's not to say that the latter can't be beneficial -- it is -- but it's typically not what you want it to do. For instance, look at what happens to this function:
Code:
function foo() {
  if [ $1 = magic ]; then
    echo "Magic!!"
  else
    echo "No magic :("
  fi
}

foo magic    #  Magic!!
foo bar      #  No magic :(
foo oh no    #  No magic :(
foo "oh no"  #  bash: [: too many arguments
             #+ No magic :(
The last one might confuse you. Basically, when Bash executes that statement, it can tell the function "Hey, 'oh no' is one argument, not two", but then the function doesn't take care to acknowledge that, and so this gets called in the if statement: if [ oh no = magic ]. Obviously, you can't compare two strings to one string, and so, Bash gives you an error (And, consequently, returns a non-zero value, which is "false"). To correct that code, all you need to do is change $1 to "$1". On a side note, I have used this before to cheat at a conditional and having to write more code. It was something like:
Code:
# Hackily converts all uppercase letters in a file to lowercase, stopping at $lines if $flag is given
file="$1"
flag="$2"
lines="$3"

MAXLINES=cat
if [ "$flag" = "-m" ]; then
  MAXLINES="sed -e '$lines q'"
fi

cat "$file" | $MAXLINES | tr "[A-Z]" "[a-z]"


Bash's string manipulation functions are also extremely important. I am in awe of some of the code that I have written before I learned about them. I had terrible lines like:

Code:
newvar="$(echo "$oldvar" | sed -e "s/^...\(...\).*/\1/")"
Which, if you don't know regular expressions or can't read that code at all, simply grabs the 4th through 6th characters from a string. The version that uses Bash's string functions looks like:
Code:
newvar=${oldvar:3:3}
Which can be read as "grab the 4th character (starts at 0) and then get the next 3 characters". Bash uses, mostly, the same syntax for its functions. Namely: ${VARNAME<whatever the functions uses here>}. The more important functions are: substring (Though, only mildly), remove from beginning and end, and string replacement (Which, just so happens to be the only things on this page). Because Bash knows that you won't be using these in the super-hacky way that I did above, you don't have to put quotes around the ${} statement. Bash knows that it is one argument. The ones I use the most are the ${var#removal} and ${var%removal} (And their brothers, ## and %%). Here's some code I stole from my IRC bot tutorial to grab the username and channel from a response from an IRC server:
Code:
# Example input: ":Catherine!~Catherine@example.com PRIVMSG #cemetech :testing"
channel=${line#*PRIVMSG }      # Strip the portion from the beginning to PRIVMSG
channel=${channel%% :*}        # Strip the portion from : to the end
message=${line#*$channel :}    # Strip the portion from the beginning to $channel
username=${line%%!*}           # Strip the portion from the first ! to the end
username=${username#:}         # Strip the first :

echo "$username said '$message' to $channel"
The difference between # and ## is: # will remove the smallest match, and ## will remove the largest. For instance:
Code:
var=abc123abc

echo ${var#*abc}  # "123abc", removes the first abc
echo ${var##*abc} # "", removes the first and second abc, including the 123
echo ${var%*abc}  # "abc123", removes the last abc
echo ${var%%*abc} # "", removes both abc's


Last but not least, a shameless plug for my website! I've put several programs of my own in my /src/ directory for others to look through. I've also written several blog posts about Bash (Okay, as of now, 3, and the others are poorly written Java rants and an exhibit of how bad I am at CSS/HTML, which is already evident from the other pages Razz). I hope that anyone who wants to learn Bash can read this and not be too terribly lost... I tend to start rambling at some point, it seems. I do, of course, encourage you to ask any other questions you have here, or any clarifications that I need to make (Even if it is something from my blog). And, any links that others have given you, you _should_ use. Souvik's link is an amazing resource that I still turn to when I need clarification on certain commands. You should also develop your own style of scripting, as everyone's is different, and the only thing that matters is that you are consistent with your naming (I tend to use all caps for something global or hacky, and lowercase for locals and functions, and underscores for days when I don't feel like using camelCase Razz).
That Is a lot of information. thanks catherine!
_player1537 wrote:
This can also be used to print based on the output of another program, like, for instance, looping through each file in a directory:
Code:
for f in $(ls); do
  if [ -f $f ]; then
    echo "$f is a file"
  else
    echo "$f is not a file (Directory?)"
  fi
done

You win the Useless Use of Cat Award! Smile

The first line can be rewritten as "for f in *; do", which works when you have files with spaces or newlines in them. You also have to put quotes around the "$f" in the "if" statement for the same reason.


I still remember my teacher in my Shell and Script Programming in Unix class at my university yelling at me for putting quotes around variable like that because it "tells me you're a Windows user" (his words) if you put spaces in your file names. I certainly wasn't a Windows user (I'd been using Linux almost exclusively for years by that time, and I often put spaces in my file names because, hey, they're useful), and it contradicts what he taught earlier that semester--to write programs defensively, because you never know what a user will throw at your program. He had little fits other times when I did stuff that was legal in whatever scripting language we were using but that he didn't like, such as using multiple "BEGIN" blocks in awk. I seemed to know more about scripting languages at the start of the semester than he did. Razz </ramble>
christop wrote:
_player1537 wrote:
This can also be used to print based on the output of another program, like, for instance, looping through each file in a directory:
Code:
for f in $(ls); do
  if [ -f $f ]; then
    echo "$f is a file"
  else
    echo "$f is not a file (Directory?)"
  fi
done

You win the Useless Use of Cat Award! Smile

The first line can be rewritten as "for f in *; do", which works when you have files with spaces or newlines in them. You also have to put quotes around the "$f" in the "if" statement for the same reason.


I still remember my teacher in my Shell and Script Programming in Unix class at my university yelling at me for putting quotes around variable like that because it "tells me you're a Windows user" (his words) if you put spaces in your file names. I certainly wasn't a Windows user (I'd been using Linux almost exclusively for years by that time, and I often put spaces in my file names because, hey, they're useful), and it contradicts what he taught earlier that semester--to write programs defensively, because you never know what a user will throw at your program. He had little fits other times when I did stuff that was legal in whatever scripting language we were using but that he didn't like, such as using multiple "BEGIN" blocks in awk. I seemed to know more about scripting languages at the start of the semester than he did. Razz </ramble>

Gah! I knew I'd make a mistake somewhere. I had planned to write that as $(ls -R) and then going through that output as well as using the string manipulation things so I wouldn't have to quote, but then I decided against it to just use `ls' since it would be easier. I use quotes around all my file names, since I don't know if I'll be using my code against someone's flash drive, where they use spaces, or for things like music, which tends to have spaces everywhere. I've dropped spaces for my own files, adopting the "this-file-does-not-have-spaces.whatever" style. Either way, nice catch, and I'd be surprised if I didn't make any other mistakes Razz
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement