

Useful command-line scripts for web developers (or anyone else really) - emson
http://blog.emson.co.uk/2009/06/18-useful-bash-scripts-for-web-developers/

======
emson
I also use this natty little function in my .bash_profile to cd to the last
opened finder location.

This is a script written by a colleague. <http://www.visualcortex.co.uk/>. Add
the following function to your .bash_profile in Apple OSX. Now open a
directory in Finder, then open terminal and type __cdf __, your terminal will
now change directory to the same one as the last Finder opened.

    
    
        # function to change directory to the one set in the last opened finder.
        cdf () {
           currFolderPath=$( /usr/bin/osascript <<"			EOT"
               tell application "Finder"
                   try
                       set currFolder to (folder of the front window as alias)
                   on error
                       set currFolder to (path to desktop folder as alias)
                   end try
                   POSIX path of currFolder
               end tell
        			EOT
           )
           echo "cd to \"$currFolderPath\""
           cd "$currFolderPath"
        }

~~~
yan
Conversely, running "open dir/" will open the dir in Finder. I tend to use
that a lot.

~~~
emson
yeah useful, also "open `pwd`" to open the current directory

~~~
judofyr
What's wrong with "open ."?

~~~
emson
erm... yes good point!

------
silentbicycle
Nothing against this post in particular, but it's much more useful in the long
term to learn how to write stuff like this yourself. Compare knowing how to
cook with just having lots of recipes.

While there are certainly some people who will pick apart examples like these
and learn new tricks, I've seen enough copy-and-paste programming to know that
many won't.

~~~
nuclear_eclipse
Not to mention that many of the examples given are very inefficient ways to do
what's needed. Specifically, looking for files with "5" in the name:

    
    
        $ ls | grep -e .*5.*
    

Would be better as:

    
    
        $ find . -name '*5*'
    

or if you insist on using a regex:

    
    
        $ find . -regex '.*5.*'

~~~
greyboy
Am I missing something? What's wrong with:

    
    
      $ ls *5*
    

??

The find command is more powerful (descending into subdirs, etc.), but the
original example in the link only specified the current directory.

~~~
prodigal_erik
I have used production batch processing systems that routinely store enough
files that

    
    
      ls *5*
    

will fail because the argument list was too big for execve(2). Would I design
it that way? No, but people do (sometimes without really thinking about it),
and you still have to get work done.

New users should be taught find(1) because it always works.

~~~
greyboy
Right, I understand the problem. Find and xargs can do wonders. However,
that's usually an edge case (in my professional experience). I'm certainly not
proclaiming the advanced-ness of 'ls' in this circumstance.

However, in the example in the article, he was using "ls" piped to "grep" in
order to find all files with a 5 in the name. That would suffer from the same
consequences you mentioned, on such systems, and is inefficient and verbose.

Note, I agree with your advice to teach "find" (and "xargs") to users.

~~~
prodigal_erik
True,

    
    
      ls | grep 5
    

is reliable where

    
    
      ls *5*
    

is not. (Well, except for awful names that require "find -print0", or
preferably having the file taken out and shot along with its creator.)

I'm actually not a fan of xargs. It's more unixy, but somehow I find its
options hard to remember. Off the top of my head I find it easier to do

    
    
      find -exec blah {} +

------
sunkencity
I find it very much easier to just enter irb or run ruby with -e and hack
around with backquoted strings instead of using bash to loop through and
manipulate filenames.

a silly usecase would be reversing all the file names:

ruby -e '`ls -1`.each_line { |x| `mv #{x.chomp} #{x.chomp.reverse}` }'

pbcopy is pretty cool feature though.

~~~
emson
Yes I like the idea of using Ruby I find it a little more intuitive. Thanks.

Also you may want to look at commandlinefu.com:
<http://www.commandlinefu.com/commands/tagged/34/bash>

~~~
Xichekolas
Also fun as far as ruby on the command line goes: Rush
<http://rush.heroku.com/>

------
uggedal
> Bash script to append a .txt extension to a filename

Why?

~~~
mitechka
A more general case would be: How to change a pattern in a bunch of file names
from _X_ to _Y_ :

    
    
      for i in *X*; do mv $i ${i/X/Y}; done

~~~
ori_b
Or just use 'rename':

    
    
         $ rename s/foo$/bar/ *foo

------
surki
I often use this to watch youtube videos

mplayer `clive -e <http://www.youtube.com/watch?v=SZRyry_B7TY> | awk -F'","'
'{print $2}'`

You would need 'clive' package.

~~~
emson
Cool I like it.

------
blogimus
I frequently need to create datestamped archives.

Here is a one-line example, given two parameters. $1 is the archive name
prefix and $2 is the directory to archive.

    
    
      tar -cvzf ${1}-$(date +%Y%m%d-%H%M).tar.gz $2
    

Note, if $2 contains path information (such as absolute path), that path will
be stored in the tar. So it is usually used with the working dir as the parent
of $2.

------
jsonscripter
Is there any way to give grep some context? It's great knowing what file a
word came from, but I've never figured out how to get grep to spit out the
leading and following lines too.

~~~
rntz
from `man grep`:

    
    
         -A NUM, --after-context=NUM
                Print  NUM  lines  of  trailing context after matching lines.  Places a
                line containing a group separator (--)  between  contiguous  groups  of
                matches.  With the -o or --only-matching option, this has no effect and
                a warning is given.
    
         -B NUM, --before-context=NUM
                Print NUM lines of leading context before  matching  lines.   Places  a
                line  containing  a  group  separator (--) between contiguous groups of
                matches.  With the -o or --only-matching option, this has no effect and
                a warning is given.
    
         -C NUM, -NUM, --context=NUM
                Print  NUM  lines  of output context.  Places a line containing a group
                separator (--) between contiguous groups of matches.  With  the  -o  or
                --only-matching option, this has no effect and a warning is given.

~~~
akirk
Not that obvious (even from this description): you can simply do a grep -3 to
get three lines of context, etc.

------
antirez
Some time ago I wrote this little script in order to track, among different
virtual hosts, what is consuming too much CPU:

    
    
        #!/bin/sh
        cd /proc
        ps auxw | grep apache2 | grep 'Rl' | sed -e 's/ \+/ /g' | \
         cut -d' ' -f2 | egrep '[0-9]+' | xargs ls -l | grep cwd
    

Basically this will print a line for every instance of every apache virtual
host that is 'running' right now.

It's Linux specific.

~~~
emson
Very good, that looks really interesting.

------
dryicerx
<http://www.commandlinefu.com>

CommandLineFu is a much more generalized command-line collection, has a few
clever ones. Not just web developers, but anyone who uses *nix in general.
Specially the top rated ones

<http://www.commandlinefu.com/commands/browse/sort-by-votes>

------
mjgoins
Just a little warning: The "for i in..." paradigm breaks if the strings you're
iterating over have spaces in them. The way around that is to either use find
and/or xargs instead of "for i in", or to first set the IFS variable to a
value that doesn't contain spaces.

------
spudlyo
I sometimes in interviews I ask how to find the top 10 IP addresses that have
hit a web host in the last thousand hits.

tail -1000 access.log | cut -d' ' -f1 | sort | uniq -c | sort -rn | head

------
DannoHung
Don't use grep. Use ack.

~~~
aaronblohowiak
This comment is not nearly as useful as one that gives examples about your
reasoning (or at least a link to such.)

~~~
DannoHung
Sorry, I thought people would be intrigued and google it.

<http://betterthangrep.com/>

A quote:

"ack is a tool like grep, aimed at programmers with large trees of
heterogeneous source code.

ack is written purely in Perl, and takes advantage of the power of Perl's
regular expressions."

~~~
ori_b
Ack could have been done just as well with a 10 line shell wrapper around
grep. It would have been much faster, on top of being simpler.

~~~
DannoHung
Put thine code where thy mouth is.

