We've had these for a lot of other languages. The one for C/C++ was quite popular, so was the equivalent for Python. I thought one for BASH would be interesting too.
21 Answers
There's cd -
to go to the previously-visited directory:
/usr/local/bin> cd /i/am/a/banana
/i/am/a/banana> cd -
/usr/local/bin>
...and then there are all those useful incarnations of the BASH for-loop:
for file in *.txt; do ls $file; done
for item in $(echo foo bar baz); do echo $item; done
for num in {0..9}; do echo $num; done

- 35,264
- 10
- 43
- 55
-
2
-
2ick... I always hate seeing `seq i j` and `jot j i`. Modern bash has range expansions: for n in {1..100}; do ... – guns Jul 30 '09 at 07:28
-
2
-
1
-
1Avoid backticks, and use `for item in $(echo foo bar baz)` because: a) $(..$(..)) is easily nestable, b) backticks can be, dependent on fonts, be confused with apostrophes, and c) you need backticks to make code-layout in comments on SO. – user unknown Aug 15 '11 at 16:50
-
-
I know that `for file in *.txt; do ls $file; done` is meant as a simple example, but of course you would do `ls *.txt` directly - you would need an example with 2 invocations of '$file'. :) – user unknown Aug 15 '11 at 17:31
In a BASH script, assign an argument to variable but provide a default if it exists:
MYVAR=${1:-default}
$MYVAR will contain the first argument if one was given else "default".

- 7,677
- 6
- 40
- 58
-
1Not to mention this snippet's cousin: MYVAR=${OTHER_VAR:=default} which sets the value of OTHER_VAR to default if it is unset. Above only uses the default only uses the default value in this instance and leaves $1 unset. – Rob Wells Jun 10 '09 at 11:28
G'day,
My favourite, and it's applicable to other shells that support aliases, is the simple way of temporarily disabling an alias by prepending a backslash to a command.
So:
alias rm='rm -i'
would always give you interactive mode when entering rm, entering
\rm
on the command line bypasses the alias.
HTH
cheers,

- 36,220
- 13
- 81
- 146
-
pretty much essential. You can always override it by using rm -f – Chris Huang-Leaver Jun 10 '09 at 11:03
-
@Chris, yep. I was more interested in showing how to disable aliased commands temporarily though. (-: – Rob Wells Jun 10 '09 at 11:25
This is not so useful, but really interesting:
history | awk '{print $2}' | awk 'BEGIN {FS="|"}{print $1}' | sort | uniq -c | sort -n | tail | sort -nr
It prints the 10 most used commands.
EDIT: This question is really similar to this.

- 1
- 1

- 512
- 1
- 6
- 21
Found this somewhere on the net a long time ago:
function bashtips {
cat <<EOF
DIRECTORIES
-----------
~- Previous working directory
pushd tmp Push tmp && cd tmp
popd Pop && cd
GLOBBING AND OUTPUT SUBSTITUTION
--------------------------------
ls a[b-dx]e Globs abe, ace, ade, axe
ls a{c,bl}e Globs ace, able
\$(ls) \`ls\` (but nestable!)
HISTORY MANIPULATION
--------------------
!! Last command
!?foo Last command containing \`foo'
^foo^bar^ Last command containing \`foo', but substitute \`bar'
!!:0 Last command word
!!:^ Last command's first argument
!\$ Last command's last argument
!!:* Last command's arguments
!!:x-y Arguments x to y of last command
C-s search forwards in history
C-r search backwards in history
LINE EDITING
------------
M-d kill to end of word
C-w kill to beginning of word
C-k kill to end of line
C-u kill to beginning of line
M-r revert all modifications to current line
C-] search forwards in line
M-C-] search backwards in line
C-t transpose characters
M-t transpose words
M-u uppercase word
M-l lowercase word
M-c capitalize word
COMPLETION
----------
M-/ complete filename
M-~ complete user name
M-@ complete host name
M-\$ complete variable name
M-! complete command name
M-^ complete history
EOF
}
Add a space (or other delimiter) only if a variable is set, in order to avoid ugly unnecessary spaces.
$ first=Joe
$ last= # last name blank, the following echoes a space before the period
$ echo "Hello, $first $last. Welcome to..."
Hello, Joe . Welcome to...
$ echo "Hello, $first${last:+ $last}. Welcome to..."
Hello, Joe. Welcome to...
$ last=Green
$ echo "Hello, $first${last:+ $last}. Welcome to..."
Hello, Joe Green. Welcome to...

- 346,391
- 90
- 374
- 439
Here is a nice grep
expression to remove blank lines and comment lines:
grep -v '^[ \t]*$\|^[ \t]*#' /etc/ssh/sshd_config
The above will display the used settings in sshd_config
without any clutter.

- 9,064
- 2
- 45
- 59
To remove .svn directories you may also use the combination 'find...-prune...-exec...' (without xargs):
# tested on Mac OS X
find -x -E . \( -type d -regex '.*/\.svn/*.*' -prune \) -ls # test
find -x -E . \( -type d -regex '.*/\.svn/*.*' -prune \) -exec /bin/rm -PRfv '{}' \;
-
1I think you don't need `-exec rm` for gnu-find, since there is a -delete (but not sure about -PRfv :=verbose, force, Recursive, P?). And you don't need to mask `{}` - else I would enjoy to upvote and accept it an answer here: http://unix.stackexchange.com/q/8647/4485 – user unknown Aug 15 '11 at 16:58
Here is another one:
#!/bin/bash
# Shows the full path of files, good for copy pasting and for when
# listing the full paths is necessary.
# Usage: Run in the working directory (no path), otherwise takes the
# same file specification as ls.
for file in $(ls "$@"); do
echo -n $(pwd)
[[ $(pwd) != "/" ]] && echo -n /
echo $file
done
At the beginning of a script that must be run as root:
if [ `id -u` != 0 ]; then
echo "This script must be run as root" 1>&2
exit 1
fi

- 24,487
- 15
- 68
- 80
-
-
1The `!= 0` is superfluous, and it can be shortened to `test $(id -u) && echo "This ..." && exit 1` – user unknown Aug 15 '11 at 17:02
-
@userunknown: That line makes no sense. Won't the `id -u` answer with the user id, and regardless have an exit status of 0. unless you use a root id of 0 as the status somehow... that's what the 1>&2... in this interesting case... I check that out – J. M. Becker Dec 18 '11 at 08:02
-
... actually, if you don't care about using bashisms... You could write it like this also. `(( \`id -u\` )) && echo "Must be root" && exit 1` – J. M. Becker Dec 18 '11 at 08:19
I use this one a lot in conjunction with Java development:
#!/bin/sh if [ "$1" == "" ] || [ "$2" == "" ]; then echo "Usage jarfinder.sh " exit fi SEARCH=`echo $2 | sed -e 's/[\\\/]/./g'` echo Searching jars and zips in $1 for "$SEARCH" find $1 -type f -printf "'%p'\n" | egrep "\.(jar|zip)'$" | sed -e "s/\(.*\)/echo \1 ; jar tvf \1 | sed -e 's\/^\/ \/' | grep -i \"$SEARCH\"/" | sh
which I keep in my collection of handy scripts.
I also use this one-liner a lot:
find . -name "*.java" | xargs grep -li "yadayada"
end this one:
find . -name "*.java" | sed -e 's+\(.*\)+echo \1 ; yada_cmd \1+' | sh

- 13,631
- 10
- 59
- 101
!find:p ......... show last find command - not execute
# create one dir and go to
echo 'mkcd() { mkdir -p "$@" && cd $_; }' >> ~/.bashrc
# backup file in single command
cp /path/too/long/to/file{,.backup}

- 11,069
- 3
- 50
- 40
If you like to have your current working directory in your prompt ($PS1
), are running in a terminal with only 80 columns, and sometimes work in really deep hierarchies, you can end up with a prompt that takes all but about 5 characters of your line. In that case, the following declarations are helpful:
PS1='${PWD##$PREFIX}$ '
PREFIX='' export PREFIX
prefix () {
PREFIX="$1"
}
prefix '*/'
The prefix '*/'
call will set your prompt to only contain the last directory element of your current working directory (instead of the complete path). If you want to see the entire path, call prefix
with no arguments.

- 300
- 1
- 7
I love the backtick operator.
gcc `pkg-config <package> --cflags` -o foo.o -c foo.c
And:
hd `whereis -b ls | sed "s/ls: //"` | head
Knowing me, I've missed a more efficient way of 'head'ing the hexdump of a binary which you don't know the location of... oh, and as is fairly obvious, "ls" can be swapped out with a variable so in a script it would go something like:
#!/bin/bash
hd `whereis -b $1 | sed "s/$1: //"` | head
The practical usefulness of the above is fairly limited but it demonstrates the versatility of the backtick operator (and the bash shell) fairly well, in my humble opinion.

- 1,582
- 3
- 15
- 33
We develop websites and store code for them in SVN. When moving to production we don't want the .svn directories to show up. The following code recurses directories and removes unwanted ones (could be used for any unwanted directories). Not strictly bash but useful nonetheless.
find . -type d -name .svn | xargs rm -rf
execute from the top most path in the product ... of course be careful as executed in the wrong place could cause very bad things to happen.
You could also do a regular file by changing -type d to -type f

- 19,191
- 6
- 49
- 60
-
3for svn there's also `svn export`, which exports the working directory and leaves the .svn folders as is – knittl Jun 08 '09 at 17:21
-
2The correct way to do this is: find . -type d -name .svn -exec rm -rf {} \; – Neil Jul 01 '09 at 20:24
-
I use this to indent source code by four spaces and copying the result to the clipboard in X:
cat src/Something.java | sed -e 's/^/ /g' | xsel
Now Something.java is ready to be pasted by middle clicking. I know I can reduce the expression by one pipe and remove the cat, but I like it this way as I find it easier edit the beginning when re-using the expression.
An effective (and intuitive) way to get a full canonical file path given a specified file. This would resolve all cases of symbolic links, relative file references, etc.
full_path="$(cd $(/usr/bin/dirname "$file"); pwd -P)/$(/usr/bin/basename "$file")"
I use this to launch apps in their own xterm window (or not) from the same link.
#!/bin/bash
#
# cli_app launcher -- detects where u are launching from; gui/tty
#
dev=`/usr/bin/tty`
case $dev in
/dev/pts/0 | /dev/pts/1) xterm -e /home/user/bin/cli_app ;; ## opens gui terminal
*) /home/user/bin/cli_app ;; ## opens where u are
esac
# eof #

- 9
- 2
To change all files in ~ which are owned by the group vboxusers to be owned by the user group kent instead, I created something. But as it had a weakness in using xargs I'm changing it to the solution proposed in the comment to this answer:
$ find ~ -group vboxusers -exec chown kent:kent {} \;
-
1The correct way to do this is: find ~ -group vboxusers -exec chown kent:kent {} \; – Neil Jul 01 '09 at 20:25
-
-
Too long to include in total, but the solutions to How do I manipulate $PATH elements in shell scripts? are quite useful to me...

- 1
- 1

- 98,632
- 24
- 142
- 234
: > truncate-file-to-zero-bytes.txt # without changing its permissions
See: codesnippets.joyent.com/posts/show/2067