arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Fri May 10, 2002 2:59 pm Post subject: Bash tips and tricks
_________________________________________________________________
This is going to be my tips and tricks tribute to the bash shell, which I believe is the soul of the GNU/Linux OS.
I'll post here any useful tips and tricks I'll find focusing to the bash shell. Please feel free to contribute to this section with your own set of tips and tricks.
At this time:
1. Bash history tips
2. The unknown $CDPATH variable
3. More on cd (typing errors)
4. Key bindings in bash shell
5. Bash? Please, help me!
6. The revenge of cd Twisted Evil (pushd/popd)
7. A couple of articles on tab completion including the very last features (thanks to frew and tom)
8. Here-Documents
9. First post of "SHELL PARAMETER EXPANSION" series
10. Trick: A fast way to comment-out blocks of script code
11. Using functions instead of aliases at .bashrc
12. A bizarre single-line-command to empty system logs
Last edited by arusabal on Sat Oct 12, 2002 4:31 pm, edited 20 times
in total
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Wed May 15, 2002 10:04 pm Post subject:
_________________________________________________________________
Some bash-history tips
The usage of the bash-history feature could be as fun as helpful, also it can save a lot of time if you are one of those who use bash-terminals for everything (if you are not, what the hell are you doing here with Linux Mr. Green ...just kidding Wink )
I'm not going to talk in extent about the usage of bash-history, I only want to show you a couple of tips. If you want to learn more about it you can take a look to the chapter 7 of the Bash Reference Manual (such as ramfree "pointed" long time ago, should be under every linux user's pillow Wink )
Here are the tips:
~]$ !n --Will execute the line n of the history record.
~]$ !-n --Will execute the command n lines back.
~]$ !! --Will execute the last command. As !-1 or "up-arrow + return"
~]$ !string --Will execute the most recent command starting with the given string. In my experience string is just the first characters of the first word of the command, so don't use space characters.
~]$ !?string[?] --Will execute the most recent command containing the given string. The last "?" may be omitted if the string is followed by a new line. So if the string includes space characters or similar close it with "?". This can be used to avoid the error that appears with !string when used with long strings.
~]$ ^string1^string2 --String2 will substitute string1 on the last command. Cool, isn't it? This is equivalent to !!:s/string1/string2/ which is cooler Wink Any one feels a bit like in vi?
$HISTIGNORE or How-To improve the history usage:
You might want to set up the shell variable $HISTIGNORE to avoid having consecutive duplicate commands or unuseful commands appended to the history list. So you'll get rid of the never ending story of hitting the up arrow trough simple and repetitive commands.
Here is an example of usage:
export HISTIGNORE="&:l[sl]:[fb]g:exit"
Setting this way the $HISTIGNORE, the consecutive duplicated commands, the simple calls to ls, ll, fg and bg commands without arguments, and calls to the exit command will not be appended to the history list, so navigate though it will be much easier.
Bash-history has many other interesting things, take a look to the manual! ...and forgive me for the emoticons abuse Rolling Eyes Last edited by arusabal on Thu May 16, 2002 5:38 pm, edited 1 time in
total
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Wed May 15, 2002 10:17 pm Post subject:
_________________________________________________________________
The un-known $CDPATH shell variable
This is a little known, *even to me* (as I discovered it tonight Wink ), shell variable. CDPATH does for the cd built-in command what PATH does for executables.
Please try it, you'll get surprised. For example:
Code:
~$ export CDPATH=~:/mnt:/usr/share/docs:/usr/src/RPMS:/usr/local/
So once you set it, cd win_c would take you to /mnt/win_c/, or just typing cd HTML would take you to /usr/share/doc/HTML/.... Interesting, isn't it?
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Wed May 15, 2002 10:48 pm Post subject:
_________________________________________________________________
More on cd stuff
cdspell
Have you ever got upset because you need to retype a cd to some directory command just for a little spelling error?
Well that can be avoid if you set on the cdspell option. Just open a bash terminal and type:
shopt -s cdspell
Now if you type:
cd /isr/src #<--- notice the 'i' Shocked
you'll get
[arusabal@paleo /usr/src]$
Linux is so cool!
Ofcourse you can set it to your bash_profile file, so every time you open a bash terminal you'll be helped in minor spelling errors Wink
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sat May 18, 2002 11:21 pm Post subject:
_________________________________________________________________
Key Bindings
Every one knows how to use the arrow keys to navigate trough history records, how to move forward and backwards along the command line, how to use command completion hitting the tab key, how to use the init and end keys, or other common combinations of keys, but during a bash terminal session you can use many other useful key bindings. Here I show you a list of the, to me, more useful ones:
Some common command line editing key-bindings:
Ctrl-l (as Ctrl-"L" not 1 or I)
Clear the screen (terminal) Same as `clear`, but can be used while writing a command without loosing the typing.
Ctrl-k
Kill the text from cursor position to the end of the line.
Ctrl-x backspace
Kill the text form cursor position to the beginning of the line.
Ctrl-a
Move to the start of the current line.
Ctrl-e
Move to the end of the current line.
Alt-b
Move backwards to the start of the current word or the previous. (text mode only, doesn't work in X)
Alt-f
Move to the end of the current word. (text mode only)
Ctrl-r
Reverse search history: search backwards starting at current line and moving up incrementally (see some posts above for more info).
Some other curious keybindings:
Alt-u
Uppercase the current word. (text mode only)
Alt-l ("L")
Down case the current word. (text mode only)
Alt-l ("L")
Capitalize the current word. (text mode only)
There are dozens of keybindings!!
The default line editing interface is emacs-like, if you are a vi fanatic you might want to use a vi-style line editing interface, so to switch betwen modes use this options:
set -o vi #vi-style
set -o emacs #emacs-style
Resources:
Here are some files you might check:
/etc/inputrc #System wide key bindings; you can re-read them any time by clicking ctrl-x Ctrl-r.
.inputrc #User's own settings
man 3 readline #Full information on Key Bindings and a list of them (many doesn't work on X)
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Mon May 20, 2002 5:33 pm Post subject: Getting help
_________________________________________________________________
Bash? Please, help me!
You don't have any idea of what shopt does? Are you writing an script and it is reporting a syntax error? Did you ever forget how to use the if command? Use the help sytem!!!
There are two ways of getting instant help in bash, the first one is the ultra-known trick of looking into the man bash page Shocked , there you'll find all the info about bash shell/scripting you may need; But although using the man page is a great resource of help and info, this can be some times a bit nasty because that page is one of the looooooong ones Wink . The second way of getting instant help is the help built-in command, this one is a real fast way of getting instant help on all the bash built-in commands and its syntax. Here is an example of its usage:
help syntax: help [-s] COMMAND
Code:
[user@host user]$ help if if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi The if COMMANDS are executed. If the exit status is zero, then the then COMMANDS are executed. Otherwise, each of the elif COMMANDS are executed in turn, and if the exit status is zero, the corresponding then COMMANDS are executed and the if command completes. Otherwise, the else COMMANDS are executed, if present. The exit status is the exit status of the last command executed, or zero if no condition tested true. [user@host user]$
Also, if you want a shorter output, maybe you only need to refresh your memory with the right syntax of a command, just use the option -s as follows:
Code:
[user@host user]$ help -s unset unset: unset [-f] [-v] [name ...] [user@host user]$
And finally, if you want a quick reference or a list of all the built-in commands, you'll just need to call help without arguments Wink
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Mon May 20, 2002 6:50 pm Post subject:
_________________________________________________________________
The revenge of cd (the directory stack)
Lets suppose that you are working in the directory /usr/local/src/some_cool_program_but_with_a_long_name-0.0.123-beta/sou rce/ , you read the README file and then you notice that you have to edit some files in /etc , others in your /home directory, install some dependences form /mnt/cdrom/Mandrake/RPM/ and then go back to the program's source directory to compile it... Arrghh!!!! do I need to type again that long path????
No! you are lucky, there is something cool in the bash shell called the directory stack Cool
Lets rewind a bit. We were in /usr/local/src/some_cool_program_but_with_a_long_name-0.0.123-beta/source/ , remember?
Then to change to /etc instead of using cd /etc we'll do pushd /etc.
Doing such thing the directory where we were is saved on the top of the directory stack.
Once we finish all the work, installing, editing..., to go back to the original original directory, we'll only need to execute the command popd, and we'll be back again in /usr/local/src/some_cool_program_but_with_a_long_name-0.0.123-beta/source/ (Cool, isn't it?)
Epilogue:
The Directory Stack is a list of recently visited directories.
There are 4 bash built-in commands dedicated to it:
* dirs: Display the list of the currently remembered directories.
That is also available from the $DIRSTACK shell variable.
* pushd: Adds directories to the stack as it changes the current directory.
* popd: Removes specified directories from the stack and changes the current directory to the directory removed.
* dir: (not used in mandrake because of the default alias!!). Makes the current directory be the top of the stack, and then executes the equivalent of 'cd dir'.
Check the man page (or the help built-in) to navigate through the stack and to check which are the options that those commands accept.
frew
Senior user
Joined: 01 Jun 2002
Posts: 214
Location: Mississippi
Post Posted: Sat Jun 01, 2002 10:24 am Post subject: don't forget
the tab button
_________________________________________________________________
I know you didn't ask for this one, but its a lifesaver once you get used to it. Ever have to type in a program name thats obscure or a filename too? well this should help. say you want to open a file called some_cool_program_but_with_a_long_name-0.0.123-beta.txt and you want to edit it with your favorite editlor. well instead of copy/pasting or typing that whole thing you type
vi some<tab>
and it will complete it unless there is another file that begins with some.
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sun Jun 09, 2002 2:32 am Post subject: Re: don't
forget the tab button
_________________________________________________________________
Thanks frew for your tip!
You might want to check the following post with the newer and cooler bash tab completion feature Wink
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sun Jun 09, 2002 2:36 am Post subject:
_________________________________________________________________
bash Autocompletion on Steroids... Really
cool!!!
Stolen from tom's mandrakeforum article Wink
Posted by tom on Saturday, June 08 @ 05:00:00 PDT
bash is the standard shell on Linux. If you've ever used it (*grin*),
you will know about the auto-completion feature which expands file and
directory names in path names upon hitting the TAB key.
How about auto-completion for 'rpm', 'tar', 'zip', 'chown', 'mount',
'man', 'cvs', 'ssh', image, document and sound files? No problem ...
Get the 2.05a bash RPM from Cooker. Notice that this is a package in
development and its use is not supported by Mandrakesoft. Works fine
here, though. Get the 'bash-completion-[date]-[rev].noarch.rpm' from
Ian Mcdonald's website and install it.
OK, let the fun begin ...
1. Getting the right file at once:
Code:
$ ls d* dictionary.lst dwun-0.96e-1.i386.rpm dwun- 0.96e.tar.gz $ tar tzf d[TAB]
auto-completes to the only file of those three which can be listed
by 'tar', dwun-0.96e.tar.gz. The same for rpm:
Code:
rpm -qpl d[TAB]
auto-completes to the only RPM archive starting with 'd',
dwun-0.96e-1.i386.rpm.
This behaviour is preconfigured for a load of file types,
including PDF, image and sound files.
2. List options:
Code:
cvs [TAB]
lists all available options to the 'cvs' command. Also works for
tar and rpm.
3. Complete arguments:
Code:
man 5 re[TAB] regexp_table relocated resolv.conf resolver
Especially useful with RPM:
Code:
rpm -e ope[TAB] openssh openssh-server opera openssh-clients openssl
4. List available arguments:
Code:
ssh [TAB]
lists all servers in your .known_hosts file as argument. Also
works with scp.
Code:
mount [TAB]
lists all configured mount points.
This is but a very short list of the possibilities now open to you.
Have a glance at '/etc/bash_completion' to see what commands are
covered and try them out, or configure the file to match your personal
preferences (it's weekend anyway Wink ).
As of version 20020601, some things do not work (yet). The 'service'
and 'chkconfig' autocompletion requires an extra patch to bash-2.05a.
'urpmi' and friends are listed in '/etc/bash_completion', but don't
work for me.
Nevertheless, it's quite an amazing feature, and if you spend any
considerable lenght of time on the shell, you really, really *want*
this. Smile
<end of quote>
Nothing to add, seems really, really cool Cool
The only thing is that I hope that this feature won't eat my P200MMX resources Confused ... I'm going to try it!
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sat Jul 06, 2002 9:47 am Post subject:
_________________________________________________________________
Here Documents
Back with this anarchic tribute, today I'm going to introduce the redirections from "here documents"... (maybe some day I'll make a deeper post talking about redirections, but not today).
But, what are the "here documents"?
It's just a type of redirection that instructs the shell to read the input from the current source until a line that contains only a previously defined word (whatever word). Every line read up to that point is used as input.
This kind of redirection is very useful in bash scripts, but also very helpful in shell mode.
The format of the "here documents" is something like this:
Code:
<< word document line 1 document line 2 ... document line n word
or:
Code:
<<- word document line 1 document line 2 ... document line n word
When used with '<<-' the "here document" is allowed to be indented; which will be much more pretty inside your scripts Wink
Now here comes the fun (a couple of usage examples):
*) As a replace of long "echo" strings inside a script . Some times I feel that is somewhat esthetically ugly to use many instances of "echo" or to use "echo -e" filling the text string with dozens of echo tags (n t ...).
This is much more pretty:
Code:
...your code...
function helper() {
cat <<- _END
Usage:
command -[uvhctdsat] file
where:
-u is required when...
-v bla, bla, bla
...
more blas
...
if you need more help please contact to l_torvalds@linux.org
GNU license...
bla bla...
_END #here ends the here document
}
...your code...
Doing the same thing with "echo" would have been terribly ugly. With the "here document" your script will be much more elegant.
*)Just another example, this time focused to command line:
Usage of the here documents as a fast resource of creating multiple input lines when you are working in command line mode. The example shows how to quickly instruct wget to download multiple files from different places:
Code:
[arusabal@mycomp ~]$ xargs wget -c << _Packages http://www.kernel.org/pub/linux/kernel/people/rml/preempt-kernel/v2.4/ preempt-kernel-rml-2.4.18-5.patch http://www.zipworld.com.au/~akpm/linux/2.4.18-rc1-low-latency.patch.gz http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.18.tar.gz _Packages
I'm leaving to your imagination other useful implementations of the "here document" concept
Note: there is no need at all to use "_" at the beginning of the delimiter word, but I love to do it Cool
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sat Aug 10, 2002 10:08 pm Post subject:
_________________________________________________________________
here is something very interesting for the dyslexics --like me-- that I've just discovered while surfing at http://bulmalug.net (spanish).
It's just another key binding to add to the list:
Ctrl-t
will transpose the two characters close to the cursor
For example, if you type a lot, it is quite common to change the order of the characters:
Code:
$ sl [ctrl-t]
will be 'magically' converted to:
Code:
$ ls
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Mon Sep 09, 2002 1:30 pm Post subject: SHELL PARAMETER EXPANSION (1)
_________________________________________________________________
SHELL PARAMETER EXPANSION (1)
Squeezing bash variables at maximum!
This will be the first post of a series where I'll write about the awesome world of SHELL PARAMETER EXPANSION.
If you are usually using expressions such as:
[user@host ~]$ find . -regex ".* .*" -exec sh -c 'mv "$0" "${0/ /_}"' '{}' ;
Then you probably will find this series of postings unuseful or very basic leveled... I'm not a guru, you know that Rolling Eyes But anyhow, if that's your case, you are very welcome to participate by PM me any suggestions or examples you'll want me to include here Wink
If you are staring at the above expression and you have any/many difficulty to understand what the hell is that stuff, but you feel that behind it there is something plenty of fun, then this series of posts is written for you!!! Smile
I'll try my best to introduce you the 'Shell Parameter Expansion' bash features in an useful way: with plain explanations and, more important, with as many examples as I'm able to write/find!!!
I'll try to post each time a case of shell parameter expansion with useful examples. But as I'm a *lazy guy* I can't say which will be the rate of postings that I'll follow.
Notice that this will be a series of posts! so if you feel there is something missed, don't be impatient! everything will be covered at its time!
Again feel free to contribute to this series by PM-ing me any useful examples you want to share with all of us Smile
...and sorry for my english
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sun Sep 29, 2002 12:32 pm Post subject: Trick: A fast way to comment-out blocks of script code
_________________________________________________________________
Trick: A fast way to comment-out blocks of script code
Very useful for debugging purposes
("Anonymous Here Documents")
(I know, it is supposed that I'm writing a "Bash Parameter Expansion Series of Posts" for this thread... but I don't have enough time this days for anything Crying or Very sad )
Very often is useful to comment out blocks of code while you are writing a new script and you want to debug it. There are many ways to do this, the easiest way is to add a '#' character at the very beginning of each single line of the code block. That way means to spend many time editing line by line the code adding that '#' character, and after the test is finished, you'll need to remove, again, line by line the '#'.
Certainly there are several ways to improve the commenting with '#'. For example, if you write code with vim, the commands:
:<fist line number>,<last line number>s/^/# (To comment a range of lines)
:<fist line number>,<last line number>s/^#// (To uncomment them)
should do the job in a very fast and efficient manner.
But THAT's NOT Bash!
So as this is BASH tips&tricks, I propose you a cooler way to comment out blocks of code using just a couple of BASH features combined. Those features we'll need are: the 'Here Documents' and the bash-built-in ':'.
The Bash built-in command ':' does nothing apart of expanding arguments and performing redirections. Really, it does nothing, but is very useful in many situations, for example to protect some cases of Parameter Expansion (we will see some examples in future posts), or at loops (it is an equivalent of the command 'true', see it's man page), or here, to use combined with the "Here Documents" to comment-out blocks of code creating an "Anonymous Here Doc". Its return status is always zero (=true).
The Here Documents were explained in detail some posts above.
Back to the trick, let's suppose we have a script like this:
Code:
#!/bin/bash var1=something var2=otherthing bla,bla,bla ... more code if [something]; then more things else some more fi other code here while condition; do code done and the end code exit 0 #end of script
Now, imagine that something goes wrong with the script, and we think that is due to the "end code", so we want to test just the end code, but not the if block and the while loop, so we can comment those two blocks of code by an "anonymous here document":
: << _COMMENTED_BLOCK
code line1
code line2
...
_COMMENTED_BLOCK
so the at the above script this will be:
Code:
#!/bin/bash var1=something var2=otherthing bla,bla,bla ... more code : << _COMMENT if [something]; then more things else some more fi _COMMENT other code here : << _COMMENT while condition; do code done _COMMENT and the end code exit 0 #end of script
And when we execute the script the code inside the "anonymous here documents" wont be seen by the interpreter (that's not completely true, but explaining it will be beyond this post Wink ).
This is a superb way of debugging comfortably and fast long bash scripts.
You can also use the "anonymous here documents" to create self-documenting scripts, ie:
Code:
: << _DOCUMENTATION The utility of this script is to be used as... ... then the parameters used should be... ... TODO: * Add code to do... * Check that thing... ... _DOCUMENTATION
so you'll see the documentation only when you open the script in an editor.
And that's it. I really hope that this could be of some utility for you!
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Thu Oct 03, 2002 11:53 pm Post subject: Using
functions instead of aliases at .bashrc
_________________________________________________________________
Using functions instead of aliases at .bashrc
This post has been written after a hard complaint by ramfree ( Crying or Very sad ) at help with a bash alias, and thanks to 87GTR who started that thread and joehil for providing a couple of great examples. Very Happy
In .bashrc, among other thinks you can place aliases and functions. When you open a new bash session (independently(*) if it is a login session or not) the file .bashrc gets sourced(**). That means that all what you put in there is available for you during the session.
Bash aliases are a great way to write simple shortcuts for long commands:
alias whops="ps aux | grep -v USER | cut -d' ' -f1 | sort -u"
alias lp='lp -d $PRINTER' # Use an environment variable to define the default printer
alias netscape='/opt/netscape/netscape'
But despite of their inherent advantages, aliases lack of many features that one would desire in some cases, ie: they can't take arguments (I don't mean arguments for the program called by the alias, but arguments to the alias itself):
for example:
$ alias cd2iso='dd if=/dev/scd0 of=/tmp/$1'
will never work because $1 will be expanded to an environmental variable named 1, if any. So:
$ cd2iso image.iso
will result in
"dd if=/dev/scd0 of=/tmp/ image.iso"
So in these cases, the concept of function in bash becomes very useful. Shell functions are just a way to group commands using a single name for the group, here you can see that are somewhat related to aliases, but in a deeper sense functions are more related to scripts.
Functions can accept arguments, and like in scripts, those arguments became the positional parameters during its execution.
Also notice that variables defined inside a function are local variables, so they won't be seen by the parent shell after the function ends its job.
Functions are declared using this syntax:
Code:
[ function ] name() { command-list; }
or
[ function ] name() {
commands
...
more commands
}
So in the above example, if instead of using an alias you use a function, you'll achieve your goal:
function cd2iso() { dd if=/dev/scd0 of=/tmp/$1; } # (see the original thread for a slightly different implementation of this function.)
and thus:
$ cd2iso image.iso
will result in:
"dd if=/dev/scd0 of=/tmp/image.iso"
You can create your functions as complex as you wish (they can be used, in our context -sourced by .bashrc-, as highly available scripts).
joehill posted these excellent and useful examples of functions that can be declared within .bashrc:
Code:
function mp3ren() { for i in *.mp3; do mv "$i" `echo $i | tr ' ' '_'`;done; }
function mp3dec() { for i in *.mp3; do lame --decode $i `basename $i.mp3`.wav; done; }
And I propose, using "parameter expansion" (***), this correction to avoid the usage of external commands for a "higher" performance:
Code:
function mp3ren() { for i in *.mp3; do mv "$i" "${i// /_}";done; }
function mp3dec() { for i in *.mp3; do lame --decode $i ${i%".mp3"}.wav; done; }
To end, just this quote from the Bash Reference Manual: "For almost every purpose, aliases are superseded by shell functions".
I really hope that this post had been somehow useful for you! Very Happy
(*) To achieve this you'll need to be sure that .bash_profile/.profile sources .bashrc (but that's another history).
(**) Bash reads and executes commands from .bashrc but in the current shell not in a subshell. That fact means that its variables, its aliases and its functions are available during the session.
(***) I'll post the dedicated series soon (when I'll have more free time) Smile
guest72485
Frequent user
Joined: 05 Jun 2002
Posts: 56
Post Posted: Fri Oct 04, 2002 10:47 am Post subject:
_________________________________________________________________
hey thanks buddy, that was helpful
DOlson
Moderator
Joined: 16 Apr 2002
Posts: 2393
Location: Canada
Post Posted: Sat Oct 05, 2002 6:04 am Post subject:
_________________________________________________________________
WOOHOO!!!!!!!!!!!!!
function mkcd() { mkdir $1; cd $1; }
I've always wanted to do that!!!!!!!!! Alias sucks!
joehill
Senior user
Joined: 09 May 2002
Posts: 217
Location: Toronto, Canada
Post Posted: Sat Oct 05, 2002 6:44 am Post subject:
_________________________________________________________________
sweeeeeeeeeeeet
good thinkin monsieur!
(i know how much you love that)
DOlson
Moderator
Joined: 16 Apr 2002
Posts: 2393
Location: Canada
Post Posted: Sat Oct 05, 2002 7:16 am Post subject:
_________________________________________________________________
Haha. I wanted to do that forever. I tried a bash script and everything. Nothing worked properly.
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sat Oct 05, 2002 8:56 am Post subject:
_________________________________________________________________
DOlson wrote:
WOOHOO!!!!!!!!!!!!!
function mkcd() { mkdir $1; cd $1; }
Cool! But this version will be better, since you'll prevent errors caused by the missing of an argument (destination dir):
function mkcd() { mkdir ${1?"error; usage: mkdir <new directory>"} && cd $1; }
Thanks guys for your posts, but damn! I'm very frustated right now! what about the other 12 articles!!!!!!! you are only interested in the last one. That gives the reason to ramfree Crying or Very sad Laughing
ramfree17
Moderator
Joined: 18 Apr 2002
Posts: 1262
Location: Philippines
Post Posted: Sat Oct 05, 2002 4:21 pm Post subject:
_________________________________________________________________
because thats the only one we could use on a day to day basis. Very Happy
but dont stop aru, who knows, i might have to use the others someday. but first i have to remember them and that means reading them once again.... hehehehehe..
ciao!
cannonfodder
Moderator
Joined: 16 Apr 2002
Posts: 1056
Location: Rochester, NY, USA
Post Posted: Sat Oct 05, 2002 4:54 pm Post subject:
_________________________________________________________________
I like this set of alias, its real fun!
alias bendover='clear'
alias aim='ll'
alias kickme='bendover;aim;kickme'
Rolling Eyes
DOlson
Moderator
Joined: 16 Apr 2002
Posts: 2393
Location: Canada
Post Posted: Sat Oct 05, 2002 8:59 pm Post subject:
_________________________________________________________________
arusabal wrote:
DOlson wrote:
WOOHOO!!!!!!!!!!!!!
function mkcd() { mkdir $1; cd $1; }
Cool! But this version will be better, since you'll prevent errors
caused by the missing of an argument (destination dir):
function mkcd() { mkdir ${1?"error; usage: mkdir <new directory>"} && cd $1; }
Thanks guys for your posts, but damn! I'm very frustated right now! what about the other 12 articles!!!!!!! you are only interested in the last one. That gives the reason to ramfree Crying or Very sad Laughing
I don't make misteaks.
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Sat Oct 12, 2002 4:17 pm Post subject:
_________________________________________________________________
A bizarre single-line-command to empty system logs
Another day to day "usable" trick Rolling Eyes
Today I'm very bored, so after a PM from "ian malcom" about logrotate, my ill mind decided to write a single line command to do the following:
1. Empty all the log files from /var/log, saving just the last 50 lines of each one.
2. Delete the useless (at least for me) *.gz log files.
3. Do it recursively in all the /var/log tree.
4. Must be a single line command.
5. It has to be fun, because I'm bored.
Previous status:
Code:
root@host]# du -sh /var/log 193M /var/log
There were 21 directories and 145 files (where 50 were .gz files)
The single-line command:
Code:
root@host]# find /var/log -type f -exec sh -c '[[ "${1##*.}" == "gz"]] && rm $1 || (tail -50 $1 > ${1}.tmp && cat ${1}.tmp > $1 && rm ${1}.tmp)' '{}' '{}';The result:
Code:
root@host]# du -sh /var/log 665k /var/log
and the tree command shows:
21 directories and 95 files.
Despite the command syntax is quite bizarre, you'll must admit that it is coooool!!!! Cool
The explanation:
First the most difficult here, the trick with find: Instead of executing the commands directly to the "-exec" find flag, which is almost impossible, I open a sh session with a -c flag (just reads and executes commands (and finally exits) from the string '<insert here the code>' , and any remaining argument is seen as positional arguments, that's why there are those '{}' '{}' <-- really only one is needed, but then the argument will be $0 which might confuse with normal positional arguments in scripts). For those who don't know it, '{}' is the way find shows its search results to the -exec part. To end with find, "/var/log" is the searching path and "-type f " means only files.
Now the "sh" part (remember that the searching results generated by find are passed one by one as $1 to sh -c):
Code:
[[ "${1##*.}" == "gz" ]] && rm $1 || (tail -50 $1 > ${1}.tmp && cat ${1}.tmp > $1 && rm ${1}.tmp) The first part, is just a conditional construct:
Code:
[[ "${1##*.}" == "gz" ]]That code will return true if the string that results in the "parameter expansion" stuff is equal to "gz" (Those gzip compressed log files). The expression ${1##*.} means that if the pattern "*."
matches the beginning of our parameter "$1" (ie: "/var/log/cron/errors.3.gz"), then the longest "##" matching pattern is deleted (all the stuff including the last "."), so then returning just the string "gz".
if the conditional construct returns true, then the block of code after the "&&" (and) is executed:
Code:
rm $1
That means deletion of *.gz
But if the conditional construct returns false, meaning that the file is not a gzip compressed log file, then the block of code after the "||" (or) is executed:
Code:
(tail -50 $1 > ${1}.tmp && cat ${1}.tmp > $1 && rm ${1}.tmp) I've put the code between ( ) to avoid problems of interpretation. That block of code means:
tail -50 $1 > ${1}.tmp # Save the last 50 lines of $1 to a temporary file named $1.tmp; ie: tail -50 /var/log/messages > /var/log/messages.tmp If that is achieved without error (&&), then:
cat ${1}.tmp > $1 && rm ${1}.tmp # overwrite the original file with the contents of the temporary one and finally delete the temporary file.
Again, and again: UNIX (GNU/Linux) is so cool!!!
joehill
Senior user
Joined: 09 May 2002
Posts: 217
Location: Toronto, Canada
Post Posted: Wed Oct 16, 2002 7:35 pm Post subject:
_________________________________________________________________
you are a freaking genius. really.
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Thu Oct 17, 2002 9:16 am Post subject:
_________________________________________________________________
Embarassed well, thanks, I'm just a bash junkie ( need bash to live!!! )
joehill
Senior user
Joined: 09 May 2002
Posts: 217
Location: Toronto, Canada
Post Posted: Thu Oct 17, 2002 11:35 am Post subject:
_________________________________________________________________
genius, junkie, same thing...
rolf
Moderator
Joined: 16 Apr 2002
Posts: 968
Location: Oakland, CA USA
Post Posted: Tue Nov 12, 2002 1:16 am Post subject: a tribute to
this thread
_________________________________________________________________
Thanks, all, especially arusabal. I had this thread in the back of my mind until today, when, after substantial perusal of bash resources, the answer was revealed in the use of function.
What I wanted to do was create an alias for a command line using this neato script for printing addresses, including my return address, on envelopes, giving only a text file containing the 'To' address as argument to:
/home/rolf/envelope/envelope <file> | lpr
which prints out the envelope as configured in an .enveloperc file, including a bar code, which is handy for mailing invoices for my small handyman business.
As we all know, I was not able to use a variable for the text file argument in an alias, despite lengthy trial and error. What is working is to put
function e() { /home/rolf/envelope/envelope $1|lpr; }
at the bottom of ~/.bashrc and I only have to do, in the directory containing my address files:
e <file>
to have the envelope printed out. Thanks for this helpful thread Smile
arusabal
Moderator
Joined: 17 Apr 2002
Posts: 836
Location: Spain
Post Posted: Tue Nov 12, 2002 5:22 pm Post subject:
_________________________________________________________________
You are wellcome rolf Smile
Editor's note: This thread was originally posted at the old MUB (Mandrake User Board at club-nihil). This post is the result of a 99% automatic backup, so due to its nature some text may be lost (improbable but possible).

Help
MultiQuote










