Command-Line Kung Fu: White Belt
From Open Source Bridge wiki
Come and learn some useful command-line short cuts and shell idioms that will make you vastly more productive in a Linux or Unix shell. Time permitting, we’ll even play “stump the expert”, so bring your thorniest shell problems.
Speaker: Hal Pomeranz
Return to this session's details
Contents |
Contributed notes
Why is this hard
For some reason the smarts is not being handed down, the old crowd that know this are not really sharing because they take it for granted, and the new breed that that don't know what to ask. Thus we now have this wonderful talk =)
- theres a blog that discusses this. http://blog.commandlinekungfu.com/
First this is a CLI class not a shell scripting class
We're going to be doing this hands on, we'll drop off the slides here soon.
We're going to focus on bash so if you have your own fixations then your on your own.
This talk will be geared for generalities, ie we're going to try and avoid the GNU awesomeness but in an effort to make this as useful as
If you missed something
Slides are avail on the site.
Thanks Hal Poneranz.
YTok52 YATB says you r the best
run the last command that started with
!/xrandr
ok thats kinda risky lets see what that command would be
!/sudo:p
yup thats it lets run it
!!
what if I want to deal with the last bit of the last line: !$
sudo co -l /etc/httpd/httpd.conf vi !$
what about the whole thing?
sudo mkdir /home/kevin # look back for /home/kevin sudo cp .bashrc .profile !$ # look back for all args from the prev cmd sudo chown kevin !* # look back for the args of the command two steps back (you don't want kevin) sudo chmod 755 !-2*
forgot sudo
co -l /etc/ntp.conf #!! failed sudo !!
what in cases of mistype
sudu vi #!! FAIL ^sudu^sudo
managing files and directories
find
find {list of places to look} {predicates that define what to look for} {actions to take for matches}
find by type
find regular files under dev
find /dev -type d -print
find by name
find / -name '.* *' -print
by size
find large files
find / -size +10000000c -print
by time
find every file changed in the last week
find / -mtime -7 -print
you only have day granularity, or does it...
Create a file with the right time stamp
touch -t 20080116000 timestamp
then fine for stuff that is newer
find / -newer timestamp -print
use find to figure out what the gui did
you can use the same method, create a tmp file with the current timestamp
touch /tmp/timestamp sudo find /etc -newer /tmp/timestamp
find just files that have a specific string
use exec to bring grep to the party.
{} is the substitution for find to insert the file name that matched the test yes you will need to escape the semi to end the line as you could chain multiple commands in exec.
find /usr/include -type f -exec grep -l PATH_MAX {} /;
KQiQY0 Cool! That's a clever way of looking at it!
depth first
I want to delete only empty dirs, but want to capture all any parent that would match if I delete it's child:
find . -depth -type d -d -exec rmdir {} \;
this works because rmdir will not remove non empty dirs. But it creates a bunch of warnings. if you have access to GNU find then you can use (does the same thing)
find . -type d -empty -delete
time
quickie benchmarking
time {YOUR CMD}
loops
for
for f in messages*.gz do echo ==== $f zcat $f done for f in messages*.gz; do; echo ==== $f; zcat $f
And because this is UNIX you can pipe the output
for f in messages*.gz; do echo ==== $f; zcat $f | grep .....
cmd sub
for i in `seq 1 12 ` ; do mkdir $i; done
for (C style)
for((i=1; $i < 13; $i++)); do rmdir $i; done
using for to rename files with spaces to underscores
for f in *; do mv -- "$f" ${f// /_}; done
This will clobber, ( ie 'foo bar' will over wright foo_bar if it already existed), so lets be more careful.
for f in *; do n=${f// /_}; [ -f $n] || mv -- "$f" $n; done
In short, we save off the new filename, then check to see if a file already exists, if not then do the move.
while (infinite)
lets watch traffic on eth0 with an interval:
while:; do netstat -in | grep eth0; sleep 5; done
GNU: look at watch
selecting subsets or want to cut out stuff
cut
works really well for strongly delimited data (like passwd) example will list users
cut -f1,5 -d: /etc/passwd
f is the list of feilds that you want d is the delimiter
awk
get a list of pids from ps
ps -ef | awk '{print $2}'
you could use grep to limit just to ssh
ps -ef | grep sshd | awk '{print $2}'
but awk already can do this
ps -ef | awk ' /sshd/ {print $2}'
And awk can replace cut with -F
awk -F: '{print $1 ":" $5}'
sorting
sort alphabeticaly
sort /etc/passwd
or numericly
sort -n -k3 -t: /etc/passwd
n: numeric sort k: what colum to sort by (3) t: what to delimit on (:)
work out file create time, kinda
list a dir sort by inode
ls -li | sort -n
you can kinda see groups of files that were created around the same time (if you are on a fs that hands out inodes in sequental order)
uniq
you can only remove duplicate from sorted data
OLDSCHOOL
cut -f3 -d: /etc/passwd | sort | uniq
NEWSCHOOL
cut -f3 -d: /etc/passwd | sort -u
but what if I want a count of the unique values?
uniq -c
what if I want to see the duplicates (not the unique values)
uniq -q
work out how many pids by user
ps -ef | awk '{print $1}' | sort | uniq -c | sort -nr