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 of You 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