How can I pipe the result of "find" to my bash script?

I'm trying to pipe the result of a find command to a bash script. This is to simplify (maybe automate) a process I have been working on.

This is the command I would like to run

find . -type f -iname '*.mp4' -exec echo {}|./indexer.sh \;

indexer.sh is ofc chmod +x so it can execute.

indexer.sh currently contains

#!/bin/zsh
read foo
echo "You entered '$foo'"

And if I run $ echo foo | ./indexer.sh I get the output ofYou entered 'foo'

But when I run find . -type f -iname '*.mp4' -exec echo {}|./indexer.sh \; I receive the following error message:

find: -exec: no terminating ";" or "+"
You entered ''

So how can I pipe the output of find, into my script?

1

4 Answers

I would rewrite it using a parameter instead of a read statement and piping,

find . -type f -iname '*.mp4' -exec ./indexer.sh {} \;

with the following indexer.sh,

#!/bin/zsh
echo "You entered '$1'"
1

Your misconception is that echo {}|./indexer.sh is treated as a unit. It isn't. What went wrong is that your shell interprets the pipeline before it runs find. Therefore, it's running…

find . -type f -iname '*.mp4' -exec echo {}

… and piping the result to

./indexer.sh \;

As a result, find sees {} without the \; and fails. (indexer.sh sees a superfluous ; argument and ignores it.)

To fix your misconception, you would have to do…

find . -type f -exec sh -c 'echo "{}"|./indexer.sh' \;

… since that's the only way to treat that pipeline as a single command.

Of course, that's a monstrosity. If you want to run indexer.sh once for each MP4 file, take the advice from @sudodus and avoid the pipe altogether.

The \; needs to be positioned before the pipe. Since i don't have zsh and your question is tagged with bash, i'll use bash for an example.

indexer.sh

#!/bin/bash
while read foo
do echo "You entered '$foo'"
done

execution example

$ find . -type f -iname '*.mp4' -exec echo {} \; |./indexer.sh
You entered './subdirectory/d.mp4'
You entered './subdirectory/c.mp4'
You entered './b.mp4'
You entered './a.mp4'

optimization

This use case of find could be optimized by removing the . directly after find and the whole -exec part at the end. The output of find would be the same without it.

$ find -type f -iname '*.mp4' |./indexer.sh
You entered './subdirectory/d.mp4'
You entered './subdirectory/c.mp4'
You entered './b.mp4'
You entered './a.mp4'
2

If you can't or don't want to change indexer.sh for whatever reason, you can also be explicit about your iteration with

find . -type f -iname '*.mp4' | while read file; do echo $file | ./indexer.sh; done

I use this pattern a lot. You may need to set IFS if you have spaces in your filenames, but I think you'd have that problem with the other solutions as well.

2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like