//Tips tagged bash
Latest tips by RSS
Click here to subscribe
Follow Shell-Fu on Twitter
Click here to follow
Follow Shell-Fu on identi.ca
Click here to follow
Using expansion to move a file aside without having to type the file name twice
cp ReallyLongFileNameYouDontWantToTypeTwice{,.orig}Don't forget the bash fork bomb. DO NOT TRY THIS AT HOME... Posted here so that you don't see this in a forum or a mailing list and use it without knowing:
Explanation:
- Emre
$ :(){ :|:& };:
Explanation:
:()defines a function called : (accepts no arguments)
{ :|:& }; This is the function: It calls the function itself and pipes the output to the same function ":" and puts the process in the background. (Recursive invocation) with ; it ends the function definition
:Calls the function and creates havoc.
- Emre
This is a little known and very underrated shell variable. CDPATH does for the cd built-in what PATH does for executables. By setting this wisely, you can cut down on the number of key-strokes you enter per day.
For example:
Now, whenever you use the cd command, bash will check all the directories in the $CDPATH list for matches to the directory name.
For example:
$ export CDPATH='.:~:/usr/local/apache/htdocs:/disk/backups'
Now, whenever you use the cd command, bash will check all the directories in the $CDPATH list for matches to the directory name.
multiple command output into a single program:
diff -u <(ls -c1 dir_1) <(ls -c1 dir_2)
Will show you a diff of files in the root of dir_1 and dir_2
diff -u <(ls -c1 dir_1) <(ls -c1 dir_2)
Will show you a diff of files in the root of dir_1 and dir_2
Selected Bash Keystrokes:
Ctrl-U - Cuts everything to the left
Ctrl-W - Cuts the word to the left
Ctrl-Y - Pastes what's in the buffer
Ctrl-A - Go to beginning of line
Ctrl-E - Go to end of line
Ctrl-U - Cuts everything to the left
Ctrl-W - Cuts the word to the left
Ctrl-Y - Pastes what's in the buffer
Ctrl-A - Go to beginning of line
Ctrl-E - Go to end of line
This is a simpler password generator.
Note that the 'tr' strips out everything except characters in the ranges (alphanumeric, mixed case and underscores). This is a nice approach as piping to head means the minimum number of bytes required to generate a password of appropriate length are taken from /dev/urandom vs other methods which take more than you should need but still have a chance of not having obtained enough random data to generate a password of the required length. You can change the parameter to head to get passwords of any length.
< /dev/urandom tr -dc A-Za-z0-9_ | head -c8
Note that the 'tr' strips out everything except characters in the ranges (alphanumeric, mixed case and underscores). This is a nice approach as piping to head means the minimum number of bytes required to generate a password of appropriate length are taken from /dev/urandom vs other methods which take more than you should need but still have a chance of not having obtained enough random data to generate a password of the required length. You can change the parameter to head to get passwords of any length.
From dotfiles.org; original author unknown:
### Handy Extract Program
extract () {
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xvjf $1 ;;
*.tar.gz) tar xvzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xvf $1 ;;
*.tbz2) tar xvjf $1 ;;
*.tgz) tar xvzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "'$1' cannot be extracted via >extract<" ;;
esac
else
echo "'$1' is not a valid file"
fi
}
Rename replaces string X in a set of file names with string Y.
This will change the extension of every .html file in your CWD to .php.
rename 's/.html$/.php/' *.html
This will change the extension of every .html file in your CWD to .php.
Put the following in your .bashrc file
Usage:
function calc { echo "${1}"|bc -l; }
Usage:
$ calc 2+2 4 $ calc "sqrt(2)" 1.41421356237309504880
Simulate a never-ending compilation so you have an excuse for why you're browsing the net (see http://xkcd.com/303/):
When you want to kill it, CTRL-C won't work. You have to suspend it (CTRL-Z) then kill the job (kill %1).
while true; do awk '{ print ; system("let R=$RANDOM%10; sleep $R") }' compiler.log; done
When you want to kill it, CTRL-C won't work. You have to suspend it (CTRL-Z) then kill the job (kill %1).
To remove empty directories (even if filenames or dirnames contain spaces or weird characters) from a tree you can do:
find . -type d -empty -print0 | xargs -0 rmdir
Often I find myself using Ctrl-R in Bash to get an old command, only to find that too many days have passed and it's no longer in the .bash_history file.
It is possible to increase the number of lines in the history file, but there can always be a moment when you'll need a long command from many months ago. The solution below uses the PROMPT_COMMAND variable, a command that bash executes before showing each prompt. Here are the two lines to add to your profile:
If a previous PROMPT_COMMAND was set, it gets executed before this and then appends a line of the format:
PID USER INDEX TIMESTAMP COMMAND
to a file called .bash_permanent_history in the current user home.
Adding the username is useful to distinguish between "sudo -s" sessions and normal sessions which retain the same value for "~/", and so append lines to the same .bash_permanent_history file.
It is possible to increase the number of lines in the history file, but there can always be a moment when you'll need a long command from many months ago. The solution below uses the PROMPT_COMMAND variable, a command that bash executes before showing each prompt. Here are the two lines to add to your profile:
export HISTTIMEFORMAT="%s "
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND ; }"'echo $$ $USER \ "$(history 1)" >> ~/.bash_permanent_history'
If a previous PROMPT_COMMAND was set, it gets executed before this and then appends a line of the format:
PID USER INDEX TIMESTAMP COMMAND
to a file called .bash_permanent_history in the current user home.
Adding the username is useful to distinguish between "sudo -s" sessions and normal sessions which retain the same value for "~/", and so append lines to the same .bash_permanent_history file.
I'm frequently logged into multiple different boxes concurrently. To help me keep track of which box I'm working on at the moment, I have this in my .bashrc file, which I keep rsynced across the various boxes.
.colors.sh:
# defines the color variables used below, including ${Normal} # google "tput setaf" and "tput setab" for more information . ~/.colors.sh if [ `id -u` -eq 0 ]; then Color=${RedBG}${White} # red background for root else case `hostname` in machine1 ) Color=${Blue} ;; machine2 ) Color=${Green} ;; machine3 ) Color=${Cyan} ;; machine4 ) Color=${Purple} ;; * ) Color=${Yellow} ;; esac fi PS1="${Color}$PS1${Normal}\n> "
.colors.sh:
Black="$(tput setaf 0)" BlackBG="$(tput setab 0)" DarkGrey="$(tput bold ; tput setaf 0)" LightGrey="$(tput setaf 7)" LightGreyBG="$(tput setab 7)" White="$(tput bold ; tput setaf 7)" Red="$(tput setaf 1)" RedBG="$(tput setab 1)" LightRed="$(tput bold ; tput setaf 1)" Green="$(tput setaf 2)" GreenBG="$(tput setab 2)" LightGreen="$(tput bold ; tput setaf 2)" Brown="$(tput setaf 3)" BrownBG="$(tput setab 3)" Yellow="$(tput bold ; tput setaf 3)" Blue="$(tput setaf 4)" BlueBG="$(tput setab 4)" LightBlue="$(tput bold ; tput setaf 4)" Purple="$(tput setaf 5)" PurpleBG="$(tput setab 5)" Pink="$(tput bold ; tput setaf 5)" Cyan="$(tput setaf 6)" CyanBG="$(tput setab 6)" LightCyan="$(tput bold ; tput setaf 6)" Normal="$(tput sgr0)" # No Color
I often use 'screen' to run a command that I want to leave running when I logout but sometimes I forget and kick off a long job without screen. If you want to keep these things running, the following command will close the shell keeping all subprocess running
More information on the bash man page:
disown -a && exit
More information on the bash man page:
man bash | grep -A9 "disown \["
Find all files with given name (you can use Bash expansion if you'd like), and Grep for a phrase:
To display the filename that contained a match, use -print:
Or, use Grep options to print the filename and line number for each match:
The string `{}` is replaced by the current filename being processed everywhere it occurs in the arguments to the command. See the `find` man page for more information.
find . -name-exec grep "phrase" {} \;
To display the filename that contained a match, use -print:
find . -name-exec grep "phrase" {} \; -print
Or, use Grep options to print the filename and line number for each match:
find . -name-exec grep -Hn "phrase" {} \;
The string `{}` is replaced by the current filename being processed everywhere it occurs in the arguments to the command. See the `find` man page for more information.
If, like me, you often make mistakes on the command line, try using the history shortcut '^^' to repeat the last command with changes.
For example:
For example:
$ cat fiel cat: fiel: No such file or directory $ ^el^le cat file
ssh -l <login> -L <port>:<destination:port> <proxymachine> <local addy>
example
ssh -l foo -L 5000:192.168.5.2:443 192.168.1.1 https://localhost:5000/
Then go to https://localhost:<port>/ to get to destination's website; through the proxy machine.
example
ssh -l foo -L 5000:192.168.5.2:443 192.168.1.1 https://localhost:5000/
Then go to https://localhost:<port>/ to get to destination's website; through the proxy machine.
The following bash script, which depends on lynx web browser, uses Google's reverse geocode service to find a nearby address given a latitude and longitude pair:
#!/bin/bash # findnearest # Usage: findnearest latitude longitude # Ex. findnearest 17.976227 -66.111016 lat=$1 long=$2 result=$(lynx -dump "http://maps.google.com/maps/geo?output=csv&oe=utf-8&ll=$lat,$long") echo $result | cut -f3- -d,
Q: If I resize my xterm while another program is running, why doesn't bash notice the change?
http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11)
Bash won't get SIGWINCH if another process is in the foreground.
Enable checkwinsize so that bash will check the terminal size when
it regains control.
Put this in your bash config somewhere (e.g. Gentoo has it in /etc/bash/bashrc):
http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11)
Bash won't get SIGWINCH if another process is in the foreground.
Enable checkwinsize so that bash will check the terminal size when
it regains control.
Put this in your bash config somewhere (e.g. Gentoo has it in /etc/bash/bashrc):
shopt -s checkwinsize
To change the extension on a group of files using only bash builtins and mv:
for i in *.txt; do mv $i ${i%%.txt}.html; doneThese handy one-liners are used to perform the famous Caesar cipher encryption where letters of the alphabet are shifted by differing margins. The same tr command can be used to encrypt and decrypt encoded files/strings.
Rot-13 encryption:
(file)
(string)
Rot-47 encryption:
(file)
(string)
Rot-13 encryption:
(file)
$ cat file|tr A-Za-z N-ZA-Mn-za-m
(string)
$ echo -n "Secret Msg"|tr A-Za-z N-ZA-Mn-za-m
Rot-47 encryption:
(file)
$ cat file|tr '!-~' 'P-~!-O'
(string)
$ echo -n "Secret Msg"|tr '!-~' 'P-~!-O'
Don't have telnet or netcat handy for making a socket connection? Most Linux distros - not likely Debian - have this functionality built directly into Bash. The following will pull my site's index source on port 80, replace with any URL.
#!/bin/bash
exec 3<>/dev/tcp/kinqpinz.info/80
echo -e "GET / HTTP/1.1\nHost: kinqpinz.info;\nConnection: close\n\n">&3
cat <&3
If you're working in bash and want to quit without saving your history, you can do so using:
$$ gives the pid of the current bash instance, and the kill ends the process. There are other ways of disabling history in bash, but this can be used with no forward planning and any time/place you like.
kill -9 $$
$$ gives the pid of the current bash instance, and the kill ends the process. There are other ways of disabling history in bash, but this can be used with no forward planning and any time/place you like.
The script below will truncate the $PWD to 1/4 of the terminal width and put it into the command prompt, all within the same bash process, no forks to tr and gawk.
function truncate_pwd
{
newPWD="${PWD/#$HOME/~}"
local pwdmaxlen=$((${COLUMNS:-80}/4))
if [ ${#newPWD} -gt $pwdmaxlen ]
then
newPWD=".+${newPWD: -$pwdmaxlen}"
fi
}
PROMPT_COMMAND=truncate_pwd
PS1="${ttyname}@\h:\${newPWD}\\$ "
Make a backup of existing files, afterwards copy new files from somedir:
1. Go to proddir
1. Go to proddir
ls /update-200805/ |xargs -n1 -I xxx cp xxx xxx.`date +%Y%m%d` ; cp /update-200805/* .

