Found a neat trick for doing recursive one-liners

This is probably something everyone in here already knows about, but I
thought it was cool enough that I wanted to post about it.

If you want to create a one liner to say search all the *.txt files
in and under the current directory for text matching “Hello”, you can do
this

find -name ‘*.txt’ -exec ruby -ne ‘print if /Hello/’ ‘{}’ ‘;’

I know you can do this in pure ruby in like 3 lines if you use the Find
module, but I really wanted to do it with a one liner. Earlier I tried
something like this

ruby -ne ‘print if /Hello/’ find -name '*.txt'

unfortunately that version would fail if there were any spaces in the
filenames.

–Cool to use throw ruby into the -exec but I would just use grep in
that scenerio.

Or you can use the tools designed for finding stuff :slight_smile:

find . -name “*.txt” | xargs grep Hello

That version will work for all files. You can play with find to match
any file you want.

Pat

Hi,

At Tue, 27 Dec 2005 12:57:53 +0900,
Gary W. wrote in [ruby-talk:172611]:

I know you can do this in pure ruby in like 3 lines if you use the Find
module, but I really wanted to do it with a one liner. Earlier I tried
something like this

ruby -ne ‘print if /Hello/’ find -name '*.txt'

unfortunately that version would fail if there were any spaces in the
filenames.

ruby -ne ‘BEGIN{ARGV.replace(Dir[ARGV.join("\0")])}; print if /Hello/’
‘**/*.txt’

I apologize for using a brain dead example. I was more excited about
the
prospect of hitting all files under the current directory recursively,
not
the actual processing I used in my examples. Thanks for the pointer to
xargs. I didn’t know about that one, I’ll have to take a closer look at
it’s man page.

Ara, I always love your examples! :slight_smile: Please keep contributing to the
community!!

BTW, I have the process management class working like a champ… I’ll
share the code with you later!

On Tue, 27 Dec 2005, Gary W. wrote:

module, but I really wanted to do it with a one liner. Earlier I tried
something like this

ruby -ne ‘print if /Hello/’ find -name '*.txt'

ruby -e’ puts Dir["/"].select{|e| e =~ /a.rb/} ’

-a

I know Im a n00b, but I think more than anything, its good to see you so
excited about Ruby. Learning new things really is fun in Ruby.

On Mon, 26 Dec 2005 20:22:52 -0800, Gary W. [email protected]

Pat M. wrote:

Or you can use the tools designed for finding stuff :slight_smile:

find . -name “*.txt” | xargs grep Hello

That version will work for all files. You can play with find to match
any file you want.

Assuming you are on a machine with find, xargs, and grep, as opposed to
just Ruby.

I like the idea of assembling command line utils that will work on any
platform where Ruby is installed (e.g., all the machines in my house).

I also like the idea of reinventing the wheel in Ruby because sometimes
you get a better wheel. Or at least one that is more hackable.

James

http://www.ruby-doc.org - Ruby Help & Documentation
Ruby Code & Style - Ruby Code & Style: Writers wanted
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com - Playing with Better Toys
http://www.30secondrule.com - Building Better Tools

Hi –

On Tue, 27 Dec 2005, [email protected] wrote:

I know you can do this in pure ruby in like 3 lines if you use the Find
module, but I really wanted to do it with a one liner. Earlier I tried
something like this

ruby -ne ‘print if /Hello/’ find -name '*.txt'

ruby -e’ puts Dir[“/”].select{|e| e =~ /a.rb/} ’

We’ve strayed a little from the original thing, but along those lines
you could also do:

ruby -e ‘puts Dir[“/”].grep(/a.rb/)’

(just guessing about the . part :slight_smile:

or maybe even:

ruby -e 'puts Dir[“**/a.rb/”]

David


David A. Black
[email protected]

“Ruby for Rails”, from Manning Publications, coming April 2006!

Ara,

On Tue, 2005-12-27 at 13:22 +0900, [email protected] wrote:

I know you can do this in pure ruby in like 3 lines if you use the Find
module, but I really wanted to do it with a one liner. Earlier I tried
something like this

ruby -ne ‘print if /Hello/’ find -name '*.txt'

ruby -e’ puts Dir["/"].select{|e| e =~ /a.rb/} ’

That doesn’t seem to do anything . .

Phil.

Philip R.

Pricom Pty Limited (ACN 003 252 275 ABN 91 003 252 275)
GPO Box 3411
Sydney NSW 2001
Australia
Mobile: +61:(0)411-185-652
Fax: +61:(0)2-8221-9599
E-mail: [email protected]

In article
[email protected],
Pat M. [email protected] wrote:

Or you can use the tools designed for finding stuff :slight_smile:

find . -name “*.txt” | xargs grep Hello

That version will work for all files.

Not quite. For better (maximum?) robustness, pass '-print0' to find and '-0' to xargs. That will handle filenames with spaces and/or quotes correctly. (If your filenames have bytes with binary value zero in them, you still will be out of luck)

Reinder

On Tue, 27 Dec 2005, Pat M. wrote:

Or you can use the tools designed for finding stuff :slight_smile:

find . -name “*.txt” | xargs grep Hello

That version will work for all files. You can play with find to match
any file you want.

find . -regex ‘.*.txt’ -print0 | xargs -0 -n1000 grep Hello

-print0 and -0 to avoid trouble with spaces and other metagubbins.
-n1000 for a bit of a speedup
-regex to show you can :wink:

I really prefer the simple variant…
ruby -e ‘puts Dir["**/a*.{rb}"]’

finds all .rb that start with ‘a’, recursive of course :slight_smile:

Am Dienstag, 27. Dezember 2005 11:36 schrieb [email protected]:

Pat M. wrote:

Or you can use the tools designed for finding stuff :slight_smile:

find . -name “*.txt” | xargs grep Hello

That version will work for all files. You can play with find to match
any file you want.

Pat

et@adel:/tmp/rb$ touch ‘foo bar.txt’
et@adel:/tmp/rb$ find . -name “.txt"
…/foo bar.txt
et@adel:/tmp/rb$ find . -name "
.txt” | xargs grep Hello
grep: ./foo: No such file or directory
grep: bar.txt: No such file or directory
et@adel:/tmp/rb$ find . -name “*.txt” -print0 | xargs -0 grep Hello
et@adel:/tmp/rb$

Watch out if you are using xargs. It can get pretty nasty, especially if
there is not grep at work, but rm or alike.

Shooting yourself in the foot 101:
$ touch “foo … bar -rf moo.o”
$ find . -name ‘*.o’ | xargs rm
BAM

If you are using find and xargs, always use -print0 and -0,
respectively.

Regards,
Stefan

On Wed, 28 Dec 2005, Christian N. wrote:

Reinder V. [email protected] writes:

Not quite. For better (maximum?) robustness, pass '-print0' to find and '-0' to xargs. That will handle filenames with spaces and/or quotes correctly. (If your filenames have bytes with binary value zero in them, you still will be out of luck)

Know an OS where that is allowed?

NT 4 kernel mode API is quite happy with \0 in filenames. But it
really
confuses the Win32 layer! Haven’t played with later versions…

Reinder V. [email protected] writes:

Not quite. For better (maximum?) robustness, pass '-print0' to find and '-0' to xargs. That will handle filenames with spaces and/or quotes correctly. (If your filenames have bytes with binary value zero in them, you still will be out of luck)

Know an OS where that is allowed?

On Tue, 27 Dec 2005, Philip R. wrote:

ruby -e’ puts Dir["/"].select{|e| e =~ /a.rb/} ’

That doesn’t seem to do anything . .

then you probably don’t have any files named ‘a.rb’ under the current
directory - i seem to have several hundred :wink:

cheers.

-a

On Wed, 28 Dec 2005 [email protected] wrote:

then you probably don’t have any files named ‘a.rb’ under the current
directory - i seem to have several hundred :wink:

Or abrb, or acrb, or airbag, or… :slight_smile:

indeed. or diectories. that’s the nice thing about using select:

ruby -e’ puts Dir["/"].select{|e| test ?f, e and e =~ /^a.rb$/}

-a

Hi –

On Wed, 28 Dec 2005, [email protected] wrote:

On Tue, 27 Dec 2005, Philip R. wrote:

ruby -e’ puts Dir[“/”].select{|e| e =~ /a.rb/} ’

That doesn’t seem to do anything . .

then you probably don’t have any files named ‘a.rb’ under the current
directory - i seem to have several hundred :wink:

Or abrb, or acrb, or airbag, or… :slight_smile:

David


David A. Black
[email protected]

“Ruby for Rails”, from Manning Publications, coming April 2006!