4

I want to run a script in a directory in order to generate an svg file for each found dot file. Something like:

find . -name "*.dot" -exec dot -Tsvg \{} \;

This works fine but just output the result on stdout. usually I am using a redirection to generate the svg file. How can I get the dot file name to use it in the redirection like

find . -name "*.dot" -exec dot -Tsvg > "$dotfilename".svg \{} \;
Manuel Selva
  • 18,554
  • 22
  • 89
  • 134

4 Answers4

5

The following:

for i in `find . -name "*.dot"`; do
   dot -Tsvg $i > $i.svg
done

performs the find (in backticks) and loops over the results, executing dot for each one. The filename is in $i.

This uses backtick substitution and is a useful mechanism for capturing command output for subsequent use in another command.

To remove the extension and add another, use ${i%.*}.svg. See this SO answer for more info.

Community
  • 1
  • 1
Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
5

You don't need output redirection. Use -O to save to a file whose name is automatically created from the input file name and the output format.

find . -name "*.dot" -exec dot -Tsvg -O \{} \;

Just to point out that you can use {} multiple times in the argument to -exec:

find . -name "*.dot" -exec dot -Tsvg -o \{}.svg \{} \;

Where the first would produce "foo.svg" from "foo.dot", the second would produce "foo.dot.svg"

chepner
  • 497,756
  • 71
  • 530
  • 681
2

You can't do the redirection here. find does execute using execvp(3) or friends, not the shell. Instead, use shell globs, or make a script which you then can call from find

An example:

for i in ./*.dot
do
    svg=${i%.dot}.svg
    dot -Tsvg "$i" > "$svg"
done
Jo So
  • 25,005
  • 6
  • 42
  • 59
  • In bash v4 you can use globstar to get recursion from the glob. – jordanm Jul 12 '12 at 14:37
  • Yah. I don't want that crap (apart from the fact that it depends on bash). I prefer fixing my file organization should there ever be need. – Jo So Jul 12 '12 at 14:46
2

The problem that you are having is that redirection is processed before the find command. You can work around this by spawning another bash process in the -exec call. This also makes it easy to remove the extension using parameter expansion.

find . -name "*.dot" -exec bash -c 'dot -Tsvg "$1" > "${1%.*}".svg' -- {} \;
jordanm
  • 33,009
  • 7
  • 61
  • 76