Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I would like to open a discussion that would accumulate your Linux command line (CLI) best practices and tips.

I've searched for such a discussion to share the below comment but haven't found one, hence this post.

I hope we all could learn from this.

You are welcome to share your Bash tips, grep, sed, AWK, /proc and all other related Linux/Unix system administration, shell programming best practices for the benefit of us all.

share

migrated from stackoverflow.com Sep 26 '09 at 7:14

This question came from our site for professional and enthusiast programmers.

locked by Chris S Jan 27 '12 at 4:17

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site, so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. More info: help center.

show 9 more comments

85 Answers 85

I'm moving towards never typing "rm" at a command prompt. Instead, I type "ls", and if I like the list of removed files I edit the command (easily possible with bash and ksh).

Edit to add something from the comments: "rm -i" will prompt for each deletion, which accomplishes the same purpose. Thanks!

share
show 5 more comments

You can do some simple networking with bash (credit to this page and man bash):

cat < /dev/tcp/time.nist.gov/13

Yes, writing to and simultaneous reading-writing is also possible.

share
show 2 more comments

Above all, understand anything you see in the internetz before trying it out in your dev box.

share
show 1 more comment

Every now and then neither of:

find . -exec ...
find . -print0 | xargs ...
for i in *.png; do ... done

works for processing a list of files, since one needs the combined power of find, NULL separated filenames as well as plain shell loops. The solution is this little bit of bash code:

find . -print0 | while read -r -d $'\0' filename; do echo $filename; done

That allows one to process NULL separated files in a normal loop.

share
show 2 more comments

Shell-fu is a place for storing, moderating and propagating command line tips and tricks. A bit like StackOverflow, but solely for shell. You'll find plenty of answers to this question there.

share
add comment

Another trick:

When I want to make a bash alias, I just make a bash script on my user bin folder.

For instance, instead of adding the following line to my .bashrc,

alias make-symlink='ln -s -iv'

I'd make the following script and save it as ~/bin/make-symlink

#!/bin/bash                                                                     
ln -s -iv "$@"

, once the script is made executable (chmod +x), it's like I have a new alias.

Now make-symlink can be used in xargs. Also when you use a different shell (ZSH, FISH, IPYTHON, ...), make-symlink is there too.

If you use emacs, you might want to add the following to your emacs init file.

;; Make scripts executable on save                                              
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
share
add comment

The 'tee' command is really useful for when you are outputting to a file and want to see the progress at the same time. This is especially helpful for when you are logging output to a file and need to watch it as it progresses.

Instead of doing something like:

./program > file &
tail -f file

You can use the tee command on one line:

./program | tee file
share
add comment

I like to keep track of everything I do. One command that I learned in college was 'script'. This takes any output on your terminal and logs it to a file. What I didn't learn in college is how to make every terminal a script. Now I have this in my .login file:

exec script ~/.typescript/`date +%Y%m%d%H%M%S`.$$

Make sure that ~/.typescript/ exists before you add that to the end of your .login file. :)

share
add comment
  • For smaller directory trees with documentation to browse

    find .
    
  • To empty a file from shell

    > file.txt
    
  • To return to my home directory

    cd
    
share
add comment

IMHO, *nix most important command ever is... man :)

Almost everything one needs to know can be found with man and using man prevents us from interrupting our co-workers. And dealing with interruptions is one of our biggest concerns...

share
add comment

I found Git version control to be:

  • Snappy
  • A pleasure to use
  • Useful for a projects of almost any size (100K to 100GB; 1 to 100k files)

Here is how I do it:

# Create new repository
# (for now, it will live in .git/ - a single directory)
git init

# Commit all I got so far
git add .
git commit

# Add new or modified files manually
git add *.c
git status
git commit

# Add all modified files
git status
git commit -a

# Redo last commit
git commit -a --amend

# View log
git log

# Reset everything (files and git history) back to 
# what it was at 96223554b3e3b787270b1f216c19ae38e6f83ca5
git branch this-was-a-mistake
git reset --hard 9622

# Everything is back in time
ls
git log
share
add comment

Easy sums/averages/grouping with awk:

cat tests
ABC 50
DEF 70
XYZ 20
DEF 100
MNP 60
ABC 30

cat tests | awk '{sums[$1] += $2; tot += $2; qty++}\
   END { for (i in sums) 
     printf("%s %s\n", i, sums[i]); 
     printf("Total: %d\nAverage: %0.2f\n", tot, tot/qty)} ' 
MNP 60
ABC 80
XYZ 20
DEF 170
Total: 330
Average: 55.00
share
add comment

I dont these commands are in the above list...!!!

  1. find . -name .svn -type d |xargs rm -rf

    Remove all .svn folders

  2. bash -x script.sh

    print line and execute it in BASH

  3. Ctrl + [

    the same as [Esc] in vim

  4. shopt -s autocd

    Automaticly cd into directory

  5. df -i

    View the current number of free/used inodes in a file system

  6. sudo !!

    Run the last command as root

  7. python -m SimpleHTTPServer

    Serve current directory tree at http://$HOSTNAME:8000/

  8. netstat -tlnp

    Lists all listening ports together with the PID of the associated process

  9. Below are some ways to number input.txt:

    cat -n

    $ cat -n input.txt 1 123 2 3 456 4 5 789 6 7 8 abc 9 10 def 11 12 ghi

share
add comment

Output Redirection. When you're running something apend

> ~log.txt

to capture the output for later. Append

>& error_and_log.txt

for errors as well.

share
add comment

pushd and popd to temporarily switch to different directories.

So

pushd ~/tmp

will move you to that directory, but push your current location to a stack (so it can be nested).

Then

popd

to return to the previous location.

share
add comment

Turn on inline mode for tab completion for Bash:

http://codesnippets.joyent.com/posts/show/1690

share
add comment

To open remote X application on you local machine do:

ssh -X remoteuser@removeHost
konsole

This allows quickly viewing graphical applications running on remote host yet using your machine as the graphical server.

share
add comment

Copy selected text:

CTRL + SHIFT + C

...and paste it:

CTRL + SHIFT + V
share
show 1 more comment

In bash to close file descriptors: FD>&-

Close stderr:

$ function echostderr() { echo $1 >&2; }
$ echostderr "now you see me"
now you see me
$ echostderr "now you don't" 2>&-
$

Or inside a script:

$ function echostderr() { exec 2>&-; echo $1 >&2; }
$ echostderr "now you don't"
$
share
add comment

ALWAYS start any command or pipeline with # (comment) and remove it when you finish writing the command. Gives you a 2nd chance at spotting rm -rf / like things.

share
add comment

Meta+. in bash for cycling through the last argument from previous commands. Great for running tail and grep in various combinations.

share
show 1 more comment

CTRL+] x to forward search for a character "x", and Meta, CTRL+] x for backward search. On most systems, Meta can be ESC or ALT. For ESC, you press ESC then release, then combine CTRL and ], and then press the character to search for. For ALT, press down CTRL + ALT + ] at the same time, then the target character.

I find it's useful when editing history command.

For very long and very complicated command. I use fc to open vi(probably actually vim on linux) to edit the command.

share
1  
For long command editng, in bash at least, you can 'set -o vi' to enable vi-style keybindings directly in your shell. –  pboin Oct 25 '10 at 14:49
add comment

To rename a multiple files in a similar fashion I found the following script very useful and robust over the years.

It just puts the output of ls into your favorite text editor. You just modify the text, save, close. The files are renamed accordingly.

It's especially great when you combine this with Vi column editing (Ctrl-v, select a block, I to insert before or A to insert after, type text, Esc).

#!/usr/bin/ruby

RM = '/bin/rm'
MV = '/bin/mv'

from = Dir.entries('.').sort; from.delete('.'); from.delete('..')
from.sort!

from.delete_if {|i| i =~ /^\./} # Hidden files

tmp = "/tmp/renamer.#{Time.now.to_i}.#{(rand * 1000).to_i}"

File.open(tmp, 'w') do |f|
  from.each {|i| f.puts i}
end

ENV['EDITOR'] = 'vi' if ENV['EDITOR'].nil?
system("#{ENV['EDITOR']} #{tmp}")

to = File.open(tmp) {|f| f.readlines.collect{|l| l.chomp}}
`#{RM} #{tmp}`

if to.size != from.size
  STDERR.puts "renamer: ERROR: number of lines changed"
  exit(1)
end

from.each_with_index do |f, i|
  puts `#{MV} -v --interactive "#{f}" "#{to[i]}"` unless f == to[i]
end

I call this script renamer.

share
add comment

To copy part of a file system to a new hard disk one can use

mkfs.ext4 /dev/sdb
mkdir /mnt/newhd
mount /dev/sdb /mnt/newhd/
rsync -av --hard-links --acls --one-file-system --xattrs /home/maxim/ /mnt/newhd/
echo '/dev/sdb /home/maxim ext4 defaults,user_xattr,noatime 0 1' >> /etc/fstab
share
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.