Chage
If, like me, you have a web server that you leave running in the corner of the room and don't touch for weeks at a time, and you discover to your horror one day that you can't log in to it, the chances are that all the user accounts have expired.
The thing to do is reboot into single user mode (with Lilo, press escape and type "linux single"), and use the chage command to set the password expiration dates far into the future.
chage <user> runs interactively, prompting for field values.
Multiple File Search and Replace
I found various ways to do search and replace across files, but the most concise way is to use Perl:
perl -pi -w -e 's/search/replace/g;' *.txt
Bear in mind what's between the single quotes after the -e option is a line of Perl code and the search argument is a regular expression, so some characters will have special meanings. You can escape special characters (like the forward-slash, dot, caret, dollar sign, and so on) by preceeding them with a back-slash.
Of course, if you know how to use Perl and regular expressions, this incantation becomes all the more powerful!
Mandrake Cures and Tweaks
Some extremely useful Mandrake tips can be found at Ozzzy's Place, including how to set up automatic updates. Much of this will apply to other distributions as well.
Limitations Of Recursion
Many commands sport a -r or -R switch to recurse into subdirectories. I have found that with some of these, notably rm and grep, only subdirectories that match the wildcard specified in the file argument are descended into. So,
rm -rf *
will behave as expected, but
rm -rf *.html
will only delete files and (entire!) directories that end in .html. The solution is to use the output of find as the file argument instead (paying careful attention to the kinds of quotes used):
rm -rf `find . -name '*.html'`
Find Files Containing Text
I'm always piping the output of commands through grep to find specific words, but it can also be used to find files that contain a text string:
grep -lir "some text" *
The -l switch outputs only the names of files in which the text occurs (instead of each line containing the text), the -i switch ignores the case, and the -r descends into subdirectories.
Bang History
The !! event designator is substituted with the last command entered. !-2 is substituted with the one before that, and so on. For example:
which script.pl
less `!!`
Repeating A Command Sequence - Ctrl-O
If you find yourself running a sequence of commands repeatedly, Ctrl-O is your friend. Press the up arrow to find the first command in the sequence, then repeatedly press Ctrl-O to run each command in the history.
Extracting a Filename From a Path Name
If you have a variable $FILE which contains a full path and filename, for example, "/home/fred/myfile.txt", then the following code:
${FILE##/*/}
will evaluate to the filename without the path, e.g. "myfile.txt". The ## string operator deletes the longest match of the specified regular expression.
Converting Between Unix and DOS Text Files - recode
To convert from DOS/Windows files that have carriage return/linefeed pairs, to normal files with just carriage returns, use the recode command:
recode ibmpc..lat1 < file.dos > file.unix
To convert back:
recode lat1..ibmpc < file.unix > file.dos
For Loops in Bash
For loops are a useful feature in Bash for performing the same operation on a number of files. For example:
for FILE in *.dv; do dv2avi $FILE; rm $FILE; done
might convert all the .dv video files to .avi and delete the original file. Such commands can also be split across multiple lines whether in a shell script or interactively on the command line.
Listing Processes That Are Using A File - fuser
The fuser command is useful to find out which processes have a particular file open. For example, if you find you can't open the serial port, it is probably because some other program is using it.
fuser /dev/ttyS0
will do the trick. In addition, the -k switch will send the SIGKILL signal to all processes with the specified file open.