views:

158

answers:

6

Hey guys and gals,
I'm not sure if this is possible in one line (i.e., without writing a script), but I want to run an ls | grep command and then for each result, pipe it to another command.

To be specific, I've got a directory full of images and I only want to view certain ones. I can filter the images I'm interested in with ls | grep -i <something>, which will return a list of matching files. Then for each file, I want to view it by passing it in to eog.

I've tried simply passing the results in to eog like so:

eog $(ls | grep -i <something>)

This doesn't quite work as it will only open the first entry in the result list.

So, how can I execute eog FILENAME for each entry in the result list without having to bundle this operation into a script?

Edit: As suggested in the answers, I can use a for loop like so:

for i in 'ls | grep -i ...'; do eog $i; done

This works, but the loop waits to iterate until I close the currently opened eog instance.

Ideally I'd like for n instances of eog to open all at once, where n is the number of results returned from my ls | grep command. Is this possible?

Thanks everybody!

A: 

Try looping over the results:

for i in `ls | grep -i <something>`; do
    eog $i
done

Or you can one-line it:

for i in `ls | grep -i <something>`; do eog $i; done

Edit: If you want the eog instances to open in parallel, launch each in a new process with eog $i &. The updated one-liner would then read:

for i in `ls | grep -i <something>`; do (eog $i &); done
bta
Caveat: spaces in filenames might throw this off a bit. If that is the case, try using `find` instead of `ls`+`grep` and pipe the results to `xargs`.
bta
if that's the case, use shell expansion.
ghostdog74
Always use shell expansion, never use `ls`.
Philipp
@bta: I tried `do eog $i done` but I get a syntax error (unexpected token ';'). I then tried `do 'eog $i done` but that doesn't open them in parallel. Any way to make this work? Thanks.
Shakedown
@Shakedown- See my edit
bta
jilles
+3  A: 

I would use xargs:

$ ls | grep -i <something> | xargs -n 1 eog
Carl Norum
This will grep for the something in each of the files found, not grep the file *names* for the something.
Stephen P
Oops, misread. Fixing.
Carl Norum
The OP doesn't seem to want to recurse, and then it's roughly equivalent to `eog *something*`.
Philipp
@Philipp, modified.
Carl Norum
That's much worse than your previous solution, breaking on every "special" character etc. If you don't want to recurse, use `-mindepth` and `-maxdepth`.
Philipp
@Philipp, if the OP thinks `ls | grep` is ok, I think it's ok.
Carl Norum
unless you have special pattern you want to grep where normal shell expansion cannot provide, using ls with grep is useless. Use shell expansion.
ghostdog74
+1  A: 
#!/bin/bash
shopt -s nullglob
for image in *pattern*
do
  eog "$image"
done

Bash 4

#!/bin/bash
shopt -s nullglob
shopt -s globstar
for image in **/*pattern*
do
    eog "$image"
done
ghostdog74
The OP specifically requested a non-script solution.
Carl Norum
You can enter these lines in interactive mode as well.
Philipp
+2  A: 

A bare ls piped into grep is sort of redundant given arbitrary?sh*ll-glo[bB] patterns (unless there are too many matches to fit on a command line in which case the find | xargs combinations in other answers should be used.

eog is happy to take multiple file names so

eog pr0n*really-dirty.series?????.jpg

is fine and simpler.

msw
+1  A: 

Use find:

find . -mindepth 1 -maxdepth 1 -regex '...' -exec eog '{}' ';'

or

find . -mindepth 1 -maxdepth 1 -regex '...' -print0 | xargs -0 -n 1 eog

If the pattern is not too complex, then globbing is possible, making the call much easier:

for file in *.png
do
  eog -- "$file"
done

Bash also has builtin regex support:

pattern='.+\.png'
for file in *
do
  [[ $file =~ $pattern ]] && eog -- "$file"
done

Never use ls in scripts, and never use grep to filter file names.

Philipp
A: 

If you want more control over the number of arguments passed on to eog, you may use "xargs -L" in combination with "bash -c":

printf "%s\n" {1..10} | xargs -L 5 bash -c 'echo "$@"' arg0

ls | grep -i <something> | xargs -L 5 bash -c 'eog "$@"' arg0
carlo