ShellTricks
From My Admin Page
Searching
- Search for a "this OR that" search: grep "this|that"
- Search for a "this AND that" serch: awk '/this/ && /that/'
Cron to remove old/console logins
0 6 * * * who -u | egrep "\.0|old" duh | awk '{print $7}' | xargs kill -9
Add Thousands comma
from here
# echo 123456789 | /usr/bin/sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta' 123,456,789
Password Last Changed
A script (from here) which shows when user passwords were last changed, for OS's where shadow uses days past Epoch.
#!/usr/bin/perl # Output date format is YYYY-MM-DD open( S, "/etc/shadow" ); while( <S> ) { ($user,$lastchg) = (split /:/)[0,2]; @t = localtime( $lastchg*86400 ); printf "User %-8s last changed password %0.4d-%0.2d-%0.2d (%5d)\n", $user, $t[5]+1900, $t[4]+1, $t[3], $lastchg; } close( S ); exit 0;
Here's a version that shows accounts with vaild passwords and are more than 90 days old (or today-$1 if passed):
#!/usr/bin/perl # Output date format is YYYY-MM-DD # Either it is older than "today-$1" or 90 days # if (defined $ARGV[0]) {$expired = $expired = int(time() / 86400) - int($ARGV[0])} else {$expired = int(time() / 86400) - 90}; open( S, "/etc/shadow" ); while( <S> ) { ($user,$lastchg) = (split /:/)[0,2]; $pwd = (split /:/)[1]; # Check if password isn't "*","!!","*LK*","NP", or "*LK*NP" (i.e. is valid) # unless ($pwd =~ m/\*|\!\!|\*LK\*|NP|\*LK\*NP/) { @t = localtime( $lastchg*86400 ); if ($lastchg < $expired) { printf "User %-10s PW last changed %0.4d-%0.2d-%0.2d (%5d)\n", $user, $t[5]+1900, $t[4]+1, $t[3], $lastchg; } } } close( S ); exit 0;
Date Tricks
- Date minus one day, and how it works. Note "aaa" represents a non-existent timezone and can be anything that doesn't match a timezone abbreviation. the "24" part says 24 hours before current time.
Print yesterday, today, and tomorrow: # TZ=aaa24 date Tue Mar 3 14:29:52 aaa 2009 # date Wed Mar 4 08:29:53 CST 2009 # TZ=aaa-24 date Thu Mar 5 14:29:55 aaa 2009 Formatted: # TZ=aaa24 date +%Y%m%d 20090303
While Read
Here's a way to parse lines using a "while read" loop. Given the contents of "file.txt" of
1 2 3 4 5 6 7 8 9
To print each line:
cat file.txt | while read x ; do echo $x ; done 1 2 3 4 5 6 7 8 9
To parse each line into variables:
cat file.txt | while read x y z ; do echo $x $y $z ; done 1 2 3 4 5 6 7 8 9
Note that he remainder of line goes in the last variable if number of variables doesn't match number of elements on the line.
cat file.txt | while read x y ; do echo $x $y ; done 1 2 3 4 5 6 7 8 9
Add column
In this example, adds first column :
awk 'BEGIN{total=0}{total +=$1}END{print total}'
To total and add commas to total (using above) :
awk 'BEGIN{total=0}{total +=$5}END{print total}' \ | /usr/bin/sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'
Sort IP's from DNS hosts file
- grep '192\.168\.1\.' <domain>.hosts | awk '{printf "%-15s\t %s\n",$NF,$1}' | sort -t . -k 4 -un
Replace Spaces in Filenames
#!/bin/ksh ls | grep " " | while read file do target=`echo "$file"|tr -s ' '|tr ' ' '-'` mv "$file" "$target" done
Turn one column into two
To change:
1 into 1 2 2 3 4 3 4
Do:
cat <whatever> | awk '{if (NR % 2 == 1) {printf"%s ",$0} else {print $0}}'
Search / Replace a file
perl -pi -e 's/what to search/replace with this/' file*
Word Frequency Analysis
From Here. To count frequency of words in a text file (format is "<script_name> <file_name>"):
#!/bin/bash # wf.sh: Crude word frequency analysis on a text file. # This is a more efficient version of the "wf2.sh" script. # Check for input file on command-line. ARGS=1 E_BADARGS=85 E_NOFILE=86 if [ $# -ne "$ARGS" ] # Correct number of arguments passed to script? then echo "Usage: `basename $0` filename" exit $E_BADARGS fi if [ ! -f "$1" ] # Check if file exists. then echo "File \"$1\" does not exist." exit $E_NOFILE fi ######################################################## # main () sed -e 's/\.//g' -e 's/\,//g' -e 's/ /\ /g' "$1" | tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr # ========================= # Frequency of occurrence # Filter out periods and commas, and #+ change space between words to linefeed, #+ then shift characters to lowercase, and #+ finally prefix occurrence count and sort numerically. # Arun Giridhar suggests modifying the above to: # . . . | sort | uniq -c | sort +1 [-f] | sort +0 -nr # This adds a secondary sort key, so instances of #+ equal occurrence are sorted alphabetically. # As he explains it: # "This is effectively a radix sort, first on the #+ least significant column #+ (word or string, optionally case-insensitive) #+ and last on the most significant column (frequency)." # # As Frank Wang explains, the above is equivalent to #+ . . . | sort | uniq -c | sort +0 -nr #+ and the following also works: #+ . . . | sort | uniq -c | sort -k1nr -k ######################################################## exit 0