Twitter name TheHunInParis
Blog URL http://titan2x.com/
Homepage URL http://titan2x.com/

Questions asked (still waiting for an answer)

How to cut out pages from a PDF file using ghostscript or other free command line tools

A single page, or multiple pages, preferably with tools that exist not only in Linux.

by openiduser3 on Jan. 31, 2012, 8:17 p.m.

Questions asked (marked answered)

How to send an http POST to a website with a file input field

I want to test submitting to a form on a website. Creating a POST request with curl or wget is probably easy, but how does it work if the form has a file field? I want to submit a file to a form.

by openiduser3 on Feb. 6, 2012, 7:31 a.m.

How to find all hard links to a file in Solaris or GNU/Linux systems?

by openiduser3 on Dec. 23, 2011, 9:13 a.m.

One-liners posted

Run a never-ending process in the background in a way that you can check on its status anytime

bash$ screen -d -m -S some_name ping my_router

— by openiduser3 on May 17, 2012, 9:03 p.m.

Explanation

  • -d -m start screen in "detached" mode. This creates a new session but doesn't attach to it.
  • -S some_name gives the screen session a label, so you can easily re-attach to it with screen -R some_name
  • The shell prompt returns immediately, and of course you can logout too, the screen session will continue to run happily.
  • When the specified program exits (in this example ping), its screen window will also exit, and if there are no other windows in the screen session, then the screen session itself will also exit.

Make a hexdump or do the reverse with the xxd command

bash$ xxd /path/to/binary/file

— by openiduser3 on May 16, 2012, 8:22 a.m.

Explanation

This shows a very nice hexdump of the specified file. You can edit the output and convert it back to binary with xxd -r. But the best part is that you can configure vim to do all the converting back and forth for you, effectively turning vim into a binary editor, by adding this to your .vimrc:

augroup Binary
    au!
    au BufReadPre  *.bin let &bin=1
    au BufReadPost *.bin if &bin | %!xxd
    au BufReadPost *.bin set ft=xxd | endif
    au BufWritePre *.bin if &bin | %!xxd -r
    au BufWritePre *.bin endif
    au BufWritePost *.bin if &bin | %!xxd
    au BufWritePost *.bin set nomod | endif
augroup END

This will work for editing .bin files. To use it for other file extensions too, duplicate the lines within augroup and replace *.bin with *.exe for example.

This tip is from vim's :help xxd.

Really lazy way to print the first instance of $foo that occurs after $bar

bash$ ifconfig | grep ^en1 -A5 | grep inet | head -n 1

— by openiduser3 on May 12, 2012, 10:30 a.m.

Explanation

This is just for the sake of an example of finding $foo that occurs after $bar. Substitute ifconfig and the arguments of grep appropriately for your use case.

  • In the output of ifconfig there are several lines with inet. We want to get to the first one that comes after a line starting with en1
  • grep ^en1 -A5 will print the line starting with en1 and the next 5 lines that follow it
  • grep inet will print only the lines matching inet
  • head -n 1 will print only the first line

The value 5 in -A5 is really just a guess that the line we're interested in will be within the next 5 lines, the appropriate number depends on your use case.

Kind of a dumb technique, but it's easy to remember.

Replace symlinks with the actual files they are pointing at

bash$ find /path/to/dir -type l -exec sh -c 'cp --remove-destination "$(readlink "{}")" "{}"' \; 

— by openiduser3 on April 24, 2012, 1:29 p.m.

Explanation

  • All the double quoting is necessary to handle filenames with spaces.
  • Calling sh with -exec is necessary to evaluate readlink for each symlink

Limitations

The BSD implementation of cp does not have the --remove-destination flag.

Expire a user's password immediately

bash$ chage -d 0 USERNAME

— by openiduser3 on April 23, 2012, 9:05 p.m.

Explanation

This will effectively force the user to change his/her password at next login.

Limitations

Not in BSD. Yes in Linux. Don't know in UNIX.

Sort du output in Human-readable format

bash$ for i in G M K; do du -hsx * | grep "[0-9]$i\b" | sort -nr; done 2>/dev/null

— by openiduser3 on April 14, 2012, 9:06 a.m.

Explanation

  • The reason to use a for loop is to sort results with G or M or K values separately, otherwise sort -n would just sort everything by the numbers regardless of G M K suffix.
  • grep "[0-9]$i\b" matches lines containing a digit followed by G or M or K followed by a "word boundary"

Convert a decimal number to octal, hexadecimal, binary, or anything

bash$ echo 'obase=2;1234' | bc

— by openiduser3 on April 11, 2012, 9:20 p.m.

Explanation

  • bc is an arbitrary precision calculator language.
  • obase defines the conversion base for output numbers, in this example 2 (binary)
  • ; is a statement separator in bc
  • 1234 is the decimal number to convert
  • By piping the command to bc we get 1234 in binary format

Convert from avi format to mp4 encoding

bash$ ffmpeg -i file.avi file.mp4

— by openiduser3 on April 11, 2012, 9:10 p.m.

Explanation

FFmpeg is a complete, cross-platform solution to record, convert and stream audio and video. It includes libavcodec - the leading audio/video codec library.

Limitations

It is not a standard package in most systems and distros.

Format input into multiple columns, like a table, useful or pretty-printing

bash$ mount | column -t

— by openiduser3 on April 8, 2012, 2:08 p.m.

Explanation

column is a utility for formatting text. With the -t flag it detects the number of columns in the input so it can format the text into a table-like format.

For more details see man column.

A simple function to conveniently extract columns from an input stream

bash$ col() { awk '{print $'$(echo $* | sed -e 's/ /,$/g')'}'; }

— by openiduser3 on April 5, 2012, 9:36 p.m.

Explanation

Something I do a lot is extract columns from some input where cut is not suitable because the columns are separated by not a single character but multiple spaces or tabs. So I often do things like:

... | awk '{print $7, $8}'

... which is a lot of typing, additionally slowed down when typing symbols like '{}$ ... Using the simple one-line function above makes it easier and faster:

... | col 7 8

How it works:

  • The one-liner defines a new function with name col
  • The function will execute awk, and it expects standard input (coming from a pipe or input redirection)
  • The function arguments are processed with sed to use them with awk: replace all spaces with ,$ so that for example 1 2 3 becomes 1,$2,$3, which is inserted into the awk command to become the well formatted shell command: awk '{print $1,$2,$3}'

Resize an image proportionally to some specified width or height

bash$ mogrify -geometry x31 path/to/image.gif

— by openiduser3 on April 3, 2012, 7:48 p.m.

Explanation

  • mogrify is part of ImageMagick, an image manipulation software suite
  • mogrify manipulates the specified images. If you prefer to keep the original image untouched and write the manipulated image to a different file, simply replace mogrify with convert, the syntax is the same, but the last command line argument will be the target image to write to.
  • The -geometry flag is to resize the image, it requires a dimension parameter in the format WIDTHxHEIGHT
  • The dimension in this example has no width, which means the image will be resized to height=31 pixels, and the width will be proportional.

Limitations

ImageMagick is not a standard package, though it is open source and available in many systems.

Do something in another directory without going there

bash$ (cd /path/to/somewhere; tar c .) > somewhere.tar

— by openiduser3 on April 2, 2012, 8:24 p.m.

Explanation

As explained superbly in man bash:

   (list) list is executed in a subshell environment (see  COMMAND  EXECU-
          TION  ENVIRONMENT below).  Variable assignments and builtin com-
          mands that affect the  shell's  environment  do  not  remain  in
          effect  after  the  command completes.  The return status is the
          exit status of list.

In other words, this is a handy way to do something somewhere else without having to go there and coming back.

Find the target path a symlink is pointing to

bash$ readlink a_symbolic_link_to_somewhere

— by openiduser3 on March 31, 2012, 1:23 p.m.

Explanation

Sure, you could figure out the link target from the output of ls -l a_symbolic_link_to_somewhere too, but the output of readlink is simply the target of the symbolic link itself, so it is cleaner and easier to read.

Remove carriage return '\r' character in many files, without looping and intermediary files

bash$ vi +'bufdo set ff=unix' +'bufdo %s/^M$//' +q file1 file2 file3

— by openiduser3 on March 30, 2012, 1:50 p.m.

Explanation

  • The arguments starting with + are commands in vi that will be executed
  • set ff=unix is a shortcut for set fileformat=unix and means to use "unix" file format, i.e. without the carriage return \r character.
  • %s/^M$// is a pattern substitution for all lines in the entire buffer, the pattern is "carriage return at end of the line", where ^M is not two literal characters but actually one, to enter it on the command line press Ctrl followed by Enter/Return
  • bufdo means to run command in all buffers (each file is opened in a separate buffer)
  • q is to quit vi

Note: the set ff=unix is necessary, otherwise the pattern substitution will not do anything if all the lines end with \r = the file is in dos format, because in that case the line ending character will not be considered as part of the line.

Note: if a shell-script has "accidentally" some carriage returns in it, then when you try to execute you may get an error: bad interpreter: No such file or directory. This one-liner fixes that problem. If you know that all the lines in the file have the carriage return, and there is only one file to fix, then a simplified version of the one-liner is enough:

vi +'set ff=unix' +wq file1

Get the octal, hexadecimal and decimal codes of the ASCII character set

bash$ man ascii

— by openiduser3 on March 29, 2012, 7:48 a.m.

Explanation

Knowing the octal, hexadecimal or decimal code of the ASCII character set can be handy at times. In the past, too often I did things like:

perl -e 'for my $n (1 .. 255) { print $n, chr($n), $n, "\n"; }'

... when a simple man ascii would have done the trick...

On a related note, these all print the letter "A":

echo -e '\0101'
printf '\101'
printf '\x41'
perl -e 'print "\x41"'

Sort and remove duplicate lines in a file in one step without intermediary files

bash$ vi +'%!sort | uniq' +wq file.txt

— by openiduser3 on March 22, 2012, 12:09 p.m.

Explanation

We open a file with vi and run two vi commands (specified with +):

  1. %!sort | uniq
    • % = range definition, it means all the lines in the current buffer.
    • ! = run filter for the range specified. Filter is an external program, in this example sort | uniq
  2. wq = write buffer contents to file and exit.

List or edit and re-execute commands from the history list

bash$ fc -l

— by openiduser3 on March 15, 2012, 11:10 a.m.

Explanation

fc is a little known but very useful bash built-in.

  • fc -l will list the most recent 16 commands
  • fc will open the last command in a text editor defined in the environmental variable FCEDIT or EDITOR or else vi, and re-execute when you exit
  • fc 5 9 will open the history entries 5 to 9 in a text editor
  • fc -s pat=sub will run the last command after substituting pat with sub in it (does not open editor)
  • fc -s pat=sub cc is the same but on the last command starting with cc
  • fc -s cc will run the last command starting with cc

For more info see help fc.

Find the most recently modified files in a directory and all subdirectories

bash$ find /path/to/dir -type f -mtime -7 -print0 | xargs -0 ls -lt | head

— by openiduser3 on March 8, 2012, 4:10 p.m.

Explanation

  • find /path/to/dir -type f -mtime -7 -print0 prints all the files in the directory tree that have been modified within the last 7 days, with null character as the delimiter
  • xargs -0 ls -lt expects a null delimited list of filenames and will sort the files by modification time, in descending order from most recent to oldest
  • Since we are looking for the most recent files, with head we get the first 10 lines only

Note that if there are too many files in the output of find, xargs will run multiple ls -lt commands and the output will be incorrect. This is because the maximum command line length is getconf ARG_MAX and if this is exceeded xargs has to split the execution to multiple commands. So depending on your use case you may need to tweak the -mtime parameter to make sure there are not too many lines in the output.

List open files

bash$ lsof -n

— by openiduser3 on March 2, 2012, 9:01 a.m.

Explanation

With the -n flag it will not try to resolve network numbers to host names for network files, making it run a bit faster.

With the -c option you can select processes executing a matching command. And with the -t flag the output will be simply process ids without a header, suitable to use with kill. For example you can kill Google Chrome process gone crazy like this:

kill -HUP $(lsof -n -c /google/i -t)

Here /google/i is a regular expression pattern with case insensitive matching.

Set a colorful bash prompt per dev test prod environments

bash$ PS1='\[\e[1;31m\][\u@\h \W]\$\[\e[0m\] '

— by openiduser3 on Feb. 25, 2012, 1:46 p.m.

Explanation

It is useful to set a different color for the shell prompt in different deployment environments like dev/test/production, so that you don't mix up your multiple windows and do something by accident in the wrong window.

  • PS1 contains the format of the primary prompt
  • \[\e[1;31m\] sets the foreground color to red
  • \u will be substituted with the current username
  • \h will be substituted with the hostname
  • \W will be substituted with the current directory name
  • \[\e[0m\] is the end marker of the color setting

To make the color stand out even more for root users, the inverse color can be interesting too:

PS1='\[\e[7;31m\][\u@\h \W]\$\[\e[0m\] '

Other color examples:

#PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] ' # green
#PS1='\[\e[1;33m\][\u@\h \W]\$\[\e[0m\] ' # yellow
#PS1='\[\e[1;34m\][\u@\h \W]\$\[\e[0m\] ' # blue

You can learn more in man bash, search for "PROMPTING".

Limitations

Your terminal program must support colors, of course ;-)

Print the lines of file2 that are missing in file1

bash$ grep -vxFf file1 file2

— by openiduser3 on Feb. 8, 2012, 1:42 p.m.

Explanation

  • -f is to specify a file with the list of patterns: file1
  • -F is to treat the patterns fixed strings, without using regular expressions
  • -x is to match exactly the whole line
  • -v is to select non-matching lines

The result is effectively the same as:

diff file1 file2 | grep '^>' | sed -e s/..//

Limitations

The flags of grep might work differently depending on the system. So yeah you might prefer the second way which should work everywhere. Nonetheless the various of flags of grep are interesting.

Find all the unique 4-letter words in a text

bash$ cat ipsum.txt | perl -ne 'print map("$_\n", m/\w+/g);' | tr A-Z a-z | sort | uniq | awk 'length($1) == 4 {print}'

— by openiduser3 on Jan. 29, 2012, 9:28 p.m.

Explanation

  • The perl regex pattern m/\w+/g will match consecutive non-word characters, resulting in a list of all the words in the source string
  • map("$_\n", @list) transforms a list, appending a new-line at the end of each element
  • tr A-Z a-z transforms uppercase letters to lowercase
  • In awk, length($1) == 4 {print} means: for lines matching the filter condition "length of the first column is 4", execute the block of code, in this case simply print

Concatenate PDF files using GhostScript

bash$ gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=output.pdf -dBATCH file1.pdf file2.pdf file3.pdf

— by openiduser3 on Jan. 26, 2012, 7:51 a.m.

Explanation

Free PDF editing software might become more and more available, but this method has been working for a long time, and likely will continue to do so.

Limitations

It may not work with all PDFs, for example files that don't conform to Adobe's published PDF specification.

Format text with long lines to text with fixed width

bash$ fmt -s -w80 file.txt

— by openiduser3 on Jan. 22, 2012, 9:08 a.m.

Explanation

  • It will break lines longer than 80 characters at appropriate white spaces to make them less than 80 characters long.
  • The -s flag will collapse multiple consecutive white spaces into one, or at the end of a sentence a double space.

Come back quickly to the current directory after doing some temporary work somewhere else

bash$ pushd /some/where/else; work; cd /somewhere; work; cd /another/place; popd

— by openiduser3 on Jan. 15, 2012, 10:12 p.m.

Explanation

  • pushd, popd and dirs are bash builtins, you can read about them with help dirs
  • bash keeps a stack of "remembered" directories, and this stack can be manipulated with the pushd and popd builtins, and displayed with the dirs builtin
  • pushd will put the current directory on top of the directory stack. So, if you need to change to a different directory temporarily and you know that eventually you will want to come back to where you are, it is better to change directory with pushd instead of cd. While working on the temporary task you can change directories with cd several times, and in the end when you want to come back to where you started from, you can simply do popd.

Export a git project to a directory

bash$ git archive master | tar x -C /path/to/dir/to/export

— by openiduser3 on Jan. 12, 2012, 10:04 a.m.

Explanation

The git archive command basically creates a tar file. The one-liner is to create a directory instead, without an intermediate tar file. The tar command above will untar the output of git archive into the directory specified with the -C flag. The directory must exist before you run this command.

Delete all tables of a mysql database

bash$ mysql --defaults-file=my.cnf -e 'show tables' | while read t; do mysql --defaults-file=my.cnt  -e 'drop table '$t; done

— by openiduser3 on Jan. 8, 2012, 6:53 a.m.

Explanation

If you have a root access to the database, a drop database + create database is easiest. This script is useful in situations where you don't have root access to the database.

First prepare a file my.cnf to store database credentials so you don't have to enter on the command line:

[client]

database=dbname

user=dbuser

password=dbpass

host=dbhost

Make sure to protect this file with chmod go-rwx.

The one-liner will execute show tables on the database to list all tables. Then the while loop reads each table name line by line and executes a drop table command.

Limitations

The above solution is lazy, because not all lines in the output of show tables are table names, so you will see errors when you run it. But hey, shell scripts are meant to be lazy!

Calculate the total disk space used by a list of files or directories

bash$ du -s file1 dir1 | awk '{sum += $1} END {print sum}'

— by openiduser3 on Dec. 28, 2011, 7:42 p.m.

Explanation

  • This is really simple, the first column is the size of the file or the directory, which we sum up with awk and print the sum at the end.
  • Use du -sk to count in kilobytes, du -sm to count in megabytes (not available in some systems)

Concatenate two or more movie files into one using mencoder

bash$ mencoder cd1.avi cd2.avi -o movie.avi -ovc copy -oac copy

— by openiduser3 on Dec. 24, 2011, 2:51 p.m.

Explanation

  • You can specify as many files as you want on the command line to process them in sequence.
  • -ovc copy simply means to copy the video exactly
  • -oac copy simply means to copy the audio exactly
  • -o movie.avi is the output file, with all the source files concatenated

Limitations

  • mencoder is usually not a standard package
  • mencoder may be in the same package as mplayer, or maybe not
  • mencoder has binary packages for Linux, Mac and Windows

See the MPlayer homepage for more info: http://www.mplayerhq.hu/

Calculate the average execution time (of short running scripts) with awk

bash$ for i in {1..10}; do time some_script.sh; done 2>&1 | grep ^real | sed -e s/.*m// | awk '{sum += $1} END {print sum / NR}'

— by openiduser3 on Dec. 21, 2011, 7:50 a.m.

Explanation

  • The for loop runs some_script.sh 10 times, measuring its execution time with time
  • The stderr of the for loop is redirected to stdout, this is to capture the output of time so we can grep it
  • grep ^real is to get only the lines starting with "real" in the output of time
  • sed is to delete the beginning of the line up to minutes part (in the output of time)
  • For each line, awk adds to the sum, so that in the end it can output the average, which is the total sum, divided by the number of input records (= NR)

Limitations

The snippet assumes that the running time of some_script.sh is less than 1 minute, otherwise it won't work at all. Depending on your system, the time builtin might work differently. Another alternative is to use the time command /usr/bin/time instead of the bash builtin.

Check the performance of a script by re-running many times while measuring the running time

bash$ for i in {1..10}; do time curl http://localhost:8000 >/dev/null; done 2>&1 | grep real

— by openiduser3 on Dec. 17, 2011, 12:49 a.m.

Explanation

  • {1..10} creates a sequence from 1 to 10, for running the main script 10 times
  • 2>&1 redirects stderr to stdout, this is necessary to capture the "output" of the time builtin

A convenient way to re-run the previous command with sudo

bash$ sudo !!

— by openiduser3 on Dec. 14, 2011, 10:26 p.m.

Explanation

!! (bang bang!) is replaced with the previous command.

You can read more about it and other history expansion commands in man bash in the Event Designators section.

Put an ssh session in the background

bash$ ~^z

— by openiduser3 on Dec. 9, 2011, 6:44 p.m.

Explanation

  • Normally, ^z (read: ctrl-z) pauses the execution of the current foreground task. That doesn't work in an ssh session, because it is intercepted by the remote shell. ~^z is a special escape character for this case, to pause the ssh session and drop you back to the local shell.
  • For all escape characters see ~?
  • The ~ escape character must always follow a newline to be interpreted as special.
  • See man ssh for more details, search for ESCAPE CHARACTERS

Rotate a movie file with mencoder

bash$ mencoder video.avi -o rotated-right.avi -oac copy -ovc lavc -vf rotate=1

— by openiduser3 on Dec. 2, 2011, 9:30 p.m.

Explanation

mencoder is part of mplayer.

Other possible values of the rotate parameter:

  • 0: Rotate by 90 degrees clockwise and flip (default).
  • 1: Rotate by 90 degrees clockwise.
  • 2: Rotate by 90 degrees counterclockwise.
  • 3: Rotate by 90 degrees counterclockwise and flip.

Recursively remove all empty sub-directories from a directory tree

bash$ find . -type d | tac | xargs rmdir 2>/dev/null

— by openiduser3 on Nov. 29, 2011, 7:01 p.m.

Explanation

  • find will output all the directories
  • tac reverses the ordering of the lines, so "leaf" directories come first
  • The reordering is important, because rmdir removes only empty directories
  • We redirect error messages (about the non-empty directories) to /dev/null

Limitations

In UNIX and BSD systems you might not have tac, you can try the less intuitive tail -r instead.

Remove all the versioned-but-empty directories from a Subversion checkout

bash$ find . -name .svn -type d | while read ss; do dir=$(dirname "$ss"); test $(ls -a "$dir" | wc -l) == 3 && echo "svn rm \"$dir\""; done

— by openiduser3 on Nov. 27, 2011, 7:38 a.m.

Explanation

Empty directories in version control stink. Most probably they shouldn't be there. Such directories have a single subdirectory in them named ".svn", and no other files or subdirectories.

  • The "find" searches for files files named .svn that are directories
  • The "while" assigns each line in the input to the variable ss
  • The "dirname" gets the parent directory of a path, the quotes are necessary for paths with spaces
  • ls -a should output 3 lines if the directory is in fact empty: ".", "..", and ".svn"
  • If the test is true and there are precisely 3 files in the directory, echo what we want to do
  • If the output of the one-liner looks good, pipe it to | sh to really execute

Create a sequence of integer numbers

bash$ echo {4..-9}

— by openiduser3 on Nov. 24, 2011, 9:07 p.m.

Explanation

  • Useful for counters. For example, to do something 10 times, you could do for i in {1..10}; do something; done
  • Be careful, there cannot be spaces between the braces
  • As the example shows, can count backwards too

Limitations

Does not work in /bin/sh, this is bash specific.

Redirect the output of the time builtin command

bash$ { time command; } > out.out 2> time+err.out

— by openiduser3 on Nov. 20, 2011, 7:34 p.m.

Explanation

  • time is a bash builtin command, and redirecting its output does not work the same way as with proper executables
  • If you execute within braces like above, the output of time will go to stderr (standard error), so you can capture it with 2>time.out
  • An alternative is to use the /usr/bin/time executable, by referring to its full path. (The path may be different depending on your system.)

Copy a directory with a large number of files to another server

bash$ tar cp -C /path/to/dir . | ssh server2 'tar x -C /path/to/target'

— by openiduser3 on Nov. 17, 2011, 11:19 a.m.

Explanation

With a large number of files, scp or rsync can take very very long. It's much faster to tar up on one side and extract on the other. Without the -f flag tar writes output to standard output and expects input from standard input, so piping to ssh can work this way, without creating any intermediary files.

You may (or may not) gain an extra speed boost by compression, either with the z flag for tar, or with the -C flag for ssh, or with gzip pipes in the middle, like this:

tar cp -C /path/to/dir . | gzip | ssh server2 'gzip -cd | tar x -C /path/to/target'

Limitations

Depending on your system and version of tar, you may need to hyphenate the flags, for example tar -cp, and tar -x. The -C flag might also not work, but that shouldn't be too difficult to work around.

Redirect the output of multiple commands

bash$ { cmd1 ; cmd2 ; cmd3 ; } > out.out 2> err.out

— by openiduser3 on Nov. 14, 2011, 9:08 a.m.

Explanation

  • Curly braces are very helpful for grouping several commands together
  • Be careful with the syntax: 1. there must be whitespace after the opening brace 2. there must be a semicolon after the last command and before the closing brace
  • Another practical use case: test something || { echo message; exit 1; }

View a file with line numbers

bash$ grep -n ^ /path/to/file | less

— by openiduser3 on Nov. 9, 2011, 10:05 p.m.

Explanation

  • grep ^ will match all lines in a file
  • grep -n will prefix each line of output with the line number within its input file

Limitations

In some systems you might have to use egrep instead of grep.

Print the n-th and m-th line of a file

bash$ sed -ne '101 p' -e '106 p' /path/to/the/file

— by openiduser3 on Nov. 6, 2011, 10:20 p.m.

Explanation

  • The above command will print the 101th and 106th lines of the specified file.
  • The -n switch will make sed not print all lines by default.
  • The -e switch is to specify a sed command, you can use it multiple times at once.

Some sed command examples:

  • 45 p - print line #45
  • 34,55 p - print lines #34-#55
  • 99,$ p - print lines #99-end of the file

Repeat the previous command but with a string replacement

bash$ ^geomtry^geometry

— by openiduser3 on Nov. 4, 2011, 6:10 a.m.

Explanation

This can be very useful for example after a mistyped command like this:

convert -crop 745x845+0+150 my_logo.png -geomtry 400x my_logo2.png
^geomtry^geometry

"-geomtry" should have been "-geometry", the one-liner above will re-run the command with a replacement that fixes the typo.

Rename all files in the current directory by capitalizing the first letter of every word in the filenames

bash$ ls | perl -ne 'chomp; $f=$_; tr/A-Z/a-z/; s/(?<![.'"'"'])\b\w/\u$&/g; print qq{mv "$f" "$_"\n}'

— by openiduser3 on Nov. 1, 2011, 11:51 a.m.

Explanation

  • When you pipe something to perl -ne, each input line is substituted into the $_ variable. The chomp, tr///, s/// perl functions in the above command all operate on the $_ variable by default.
  • The tr/A-Z/a-z/ will convert all letters to lowercase.
  • The regular expression pattern (?<![.'])\b\w matches any word character that follows a non-word character except a dot or a single quote.
  • The messy-looking '"'"' in the middle of the regex pattern is not a typo, but necessary for inserting a single quote into the pattern. (The first single quote closes the single quote that started the perl command, followed by a single quote enclosed within double quotes, followed by another single quote to continue the perl command.) We could have used double quotes to enclose the perl command, but then we would have to escape all the dollar signs which would make everything less readable.
  • In the replacement string $& is the letter that was matched, and by putting \u in front it will be converted to uppercase.
  • qq{} in perl works like double quotes, and can make things easier to read, like in this case above when we want to include double quotes within the string to be quoted.
  • After the conversions we print a correctly escaped mv command. Pipe this to bash to really execute the rename with | sh.

Limitations

The above command will not work for files with double quotes in the name, and possibly other corner cases.

Do not save command history of current bash session

bash$ HISTFILE=

— by openiduser3 on Oct. 29, 2011, 12:41 p.m.

Explanation

The command history of the current bash session is saved to $HISTFILE when you exit the shell. If this variable is blank, the command history will not be saved.

Use rsync instead of cp to get a progress indicator when copying large files

bash$ rsync --progress largefile.gz somewhere/else/

— by openiduser3 on Oct. 18, 2011, 10:48 p.m.

Explanation

Although rsync is famous for synchronizing files across machines, it also works locally on the same machine. And although the cp command doesn't have progress indicator, which can be annoying when copying large files, but rsync does have it, so there you go.

Limitations

When copying directories be careful that the meaning of a trailing slash when specifying directories can be slightly different from cp.

Create and restore backups using cpio

bash$ find . -xdev -print0 | cpio -oa0V | gzip > path_to_save.cpio.gz

— by openiduser3 on Oct. 17, 2011, 9:06 p.m.

Explanation

To restore:

gzip -cd path_to_save.cpio.gz | cpio -imV

Why not use tar instead? cpio is slightly more accurate!

  • find . -xdev -print0 finds all files and directories without crossing over to other partitions and prints a null delimited list of filenames
  • cpio -oa0V takes the list of files to archive from stdin and creates an archive file preserving timestamps and permissions
  • cpio -imV extracts the files and directories from stdin while preserving timestamps and permissions

Get the available space on a partition as a single numeric value

bash$ df /path/to/dir | sed -ne 2p | awk '{print $4}'

— by openiduser3 on Oct. 2, 2011, 3:41 p.m.

Explanation

  • sed -ne 2p prints the 2nd line
  • awk '{print $4}' prints the 4th column

Limitations

The output of the df command might be different depending on the system, and the available space might not be the 4th column. Make the necessary adjustments depending on your system.

Schedule a one-time task using "at" command and intuitive date specifications

bash$ at now + 30 minutes

— by openiduser3 on Sept. 25, 2011, 9:30 a.m.

Explanation

  • The example will run something 30 minutes from now.
  • Another example: at 0815 wed -- run something at 8:15am on the next Wednesday.
  • With atq you can see the list of scheduled jobs, this is good to confirm that you specified the date correctly and the job will run when you want.
  • With atrm you can cancel scheduled jobs, using the job id as parameter, which you can find in the atq output.

Remove spaces recursively from all subdirectories of a directory

bash$ find /path/to/dir -type d | tac | while read LINE; do target=$(dirname "$LINE")/$(basename "$LINE" | tr -d ' '); echo mv "$LINE" "$target"; done

— by openiduser3 on Sept. 20, 2011, 2:52 p.m.

Explanation

  • find path_to_dir -type d finds all the subdirectories
  • tac reverses the order. This is important to make "leaf" directories come first!
  • target=... stuff constructs the new name, removing spaces from the leaf component and keeping everything before that the same
  • echo mv ... for safety you should run with "echo" first, if the output looks good then remove the "echo" to really perform the rename

Limitations

In UNIX or BSD there is no tac. There you can use tail -r instead.

Replace a regexp pattern in many files at once

bash$ vi +'bufdo %s/pattern/replacement/g | update' +q $(grep -rl pattern /path/to/dir)

— by openiduser3 on Sept. 15, 2011, 9:50 p.m.

Explanation

  • The inner grep will search recursively in specified directory and print the filenames that contain the pattern.
  • All files will be opened in vi, one buffer per file.
  • The arguments starting with + will be executed as vi commands:
    • bufdo %s/pattern/replacement/g | update = perform the pattern substitution in all files and save the changes
    • q = exit vi

Limitations

The :bufdo command might not be there in old versions of vim.

The first command you should run right after you login to a remote server ;-)

bash$ screen

— by openiduser3 on Sept. 15, 2011, 8:24 p.m.

Explanation

With screen you can have multiple shells in the same window. You don't need to open new windows for a second connection to the same remote server, you can simply press C-a c inside the screen session. And if your computer crashes, you screen session on the remote server survives, you can re-attach to a previous screen session with screen -R.

Find video files cached by the flash plugin in browsers

bash$ file /proc/*/fd/* 2>/dev/null | grep Flash | cut -f1 -d:

— by openiduser3 on Aug. 27, 2011, 11:46 a.m.

Explanation

Recent versions of the flash plugin hide the temporary file by marking it deleted. Practically the video stream is downloaded to a "deleted file". However, even when a file is deleted, if the file is opened by a process then you can find its file descriptor and consequently the file contents.

This simple script prints out the file descriptors of opened Flash videos:

file /proc/*/fd/* 2>/dev/null | grep Flash | cut -f1 -d:

And, you probably want to create a regular file from the file descriptor, for example:

cp $(file /proc/*/fd/* 2>/dev/null | grep Flash | cut -f1 -d: | head -n 1) video.avi

Otherwise the file descriptor is not very convenient (remember, it's a deleted file!)

The method should work regardless of your browser.

Force the preferred language when downloading a web page with wget

bash$ wget -–header='Accept-Language: en-us' http://www.timeanddate.com/calendar/index.html?year=2008&country=26 -O calendar.html

— by openiduser3 on Aug. 21, 2011, 11:40 a.m.

Explanation

When downloading web pages with wget, some websites try to be smart and detect your preferred language based on geographical location of your IP address. This can be a problem if for example you are in Japan but you want to download a page in English.

Burn the contents of a directory to dvd without needing a gui application

bash$ growisofs -dvd-compat -Z /dev/scd0 -R -J -pad /path/to/dir

— by openiduser3 on Aug. 14, 2011, 7:35 p.m.

Explanation

Useful if you have a directory full of data to burn to DVD without using a GUI. The growisofs tool is in the "dvd+rw-tools" package in Ubuntu, install it with: sudo apt-get install dvd+rw-tools

Convert all flac files in the current directory to mp3 format using "lame"

bash$ for i in *.flac; do flac -c -d "$i" | lame -m j -b 192 -s 44.1 - "${i%.flac}.mp3"; done

— by openiduser3 on Aug. 9, 2011, 7:57 p.m.

Explanation

Halt the system in Linux without the halt command or gui

bash$ echo o > /proc/sysrq-trigger

— by openiduser3 on Aug. 9, 2011, 7:55 p.m.

Explanation

  • First you need to enable the sysrq interface with: echo 1 > /proc/sys/kernel/sysrq
  • echo o > /proc/sysrq-trigger halts
  • echo b > /proc/sysrq-trigger reboots

Change to the previous directory, a shortcut for "cd $OLDPWD"

bash$ cd -

— by openiduser3 on Aug. 8, 2011, 11:31 p.m.

Explanation

Create an encrypted tar file with openssl

bash$ tar c paths_to_files_and_dirs | gzip -c | openssl des3 > encrypted.tar.gz

— by openiduser3 on Aug. 8, 2011, 11:30 p.m.

Explanation

Decrypt with: openssl des3 -d < encrypted.tar.gz | tar zx

Make another user superuser in Ubuntu

bash$ for i in $(grep :boss /etc/group | cut -f1 -d:); do adduser wife $i; done

— by openiduser3 on Aug. 5, 2011, 6:57 p.m.

Explanation

In Ubuntu the first user (created during installation) has special privileges. The privileges come from the fact that the user was automatically added to various system groups. To make another user have the same privileges, all you need to do is add the user to the same groups.

  • grep :boss /etc/group gets the group records where the user boss is the first member.
  • cut -f1 -d: gets the first column, where ":" is the column separator.
  • for i in ...; do ... ; done for each group it adds the user to the group.

Change the label of a USB drive in Linux without a gui

bash$ sudo mlabel -i /dev/sdd1 ::NewLabel

— by openiduser3 on Aug. 5, 2011, 6:57 p.m.

Explanation

Replace /dev/sdd1 with whatever your USB stick is mounted on.

Mirror from one Subversion repository to another Subversion repository

bash$ bzr co https://repo1/proj1/trunk proj1 && cd proj1 && bzr push https://repo2/vendor/proj1/trunk

— by openiduser3 on Aug. 5, 2011, 6:57 p.m.

Explanation

  • The commit history in repo1 will be copied to repo2.
  • The temporary Bazaar repository (proj1) will have the full history of changes.
  • The command above initializes the mirror. To update the mirror, run this script, you can schedule it to run periodically to keep the mirror up to date: cd proj1 && bzr up && bzr push

Limitations

  • The author information will get lost in the process.

An elegant way to rename all files in a directory to lowercase names

bash$ paste <(ls) <(ls | tr A-Z a-z) | while read OLD NEW; do echo mv -v $OLD $NEW; done

— by openiduser3 on Aug. 5, 2011, 6:57 p.m.

Explanation

  • <(cmd) is the filename of a named pipe (FIFO), where the named pipe is filled by the output of cmd
  • paste puts together the named pipes to form two columns: first column with the original filenames, second column with the lowercased filenames
  • ... | tr abc ABC transforms stdin by replacing any characters that appear in the first set of letters to the second set of letters
  • while read old new; do ...; done for each line it reads the first column into $old and the second column into $new

Limitations

  • Won't work if there are spaces in a filename.

Find Flash videos stored by browsers on a Mac

bash$ find /private/ 2>/dev/null | grep /Flash

— by openiduser3 on Aug. 5, 2011, 6:57 p.m.

Explanation

When you watch a flash video like youtube in a browser, the video file is saved on your harddisk at a temporary location. And, if you watch a video and then another video in the same window, the first one will be deleted.

Limitations

  • Might not work with all browsers.
  • Does not work with all websites (for example IMDB).
  • Does not work with an anonymous window in Chrome.

Favourite one-liners

Not implemented yet.

One-liners voted on

Not implemented yet.