The trick is to not create a list of files that you then iterate over (see e.g. Why is looping over find's output bad practice?).
find "$directory" -type f -name '*.epub' -exec ebook-convert {} output.txt \;
This finds all regular files whose name matches *.epub
in or below the $directory
directory. For each, the ebook-convert
command is executed with the pathname of the found file as its first argument and output.txt
as its second.
This would obviously overwrite output.txt
for each found file, but the following would work around that by creating a file with the same name as the original file with -converted.txt
added to the end of the name (in the same directory as the original file):
find "$directory" -type f -name '*.epub' -exec ebook-convert {} {}-converted.txt \;
This may not work with all implementations of find
as it may not replace the second {}
with the pathname of the found file (since it's concatenated with another string; but e.g. GNU find
handles it). To work around that:
find "$directory" -type f -name '*.epub' -exec sh -c '
for pathname do
ebook-convert "$pathname" "$pathname"-converted.txt
done' sh {} +
With a shell, such as bash
or zsh
, that supports the **
globbing pattern:
for pathname in "$directory"/**/*.epub; do
ebook-convert "$pathname" "$pathname"-converted.txt
done
(this requires shopt -s globstar
in bash
and will process any matching name, not just regular files, unless you use *.epub(.)
in zsh
or an explicit -f
test in bash
)