[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] help - optimization wanted for little script - batch con
From: |
Greg Wooledge |
Subject: |
Re: [Help-bash] help - optimization wanted for little script - batch converting audio files |
Date: |
Thu, 10 Jul 2014 17:06:29 -0400 |
User-agent: |
Mutt/1.4.2.3i |
On Thu, Jul 10, 2014 at 10:42:49PM +0200, Luigi Rensinghoff wrote:
> Is that supposed to work ???
>
> under OS X ??
>
>
> while IFS= read -r -d '' file; do
> echo "$file"
> done < < (find . -type f -name '*-C.aif' -print0)
You have introduced spaces between the < and (. That breaks it.
<( is a single syntax element.
<( is called "process substitution" and it works in every version of
bash going back *at least* to 1.14. So yes, it should work in Mac OS X
which I believe uses bash 3.2. Assuming, of course, you have bash
installed at all.
How it works is fairly simple: <(...) acts like a named pipe (sort of).
It sets up either a named pipe, or an object in the /dev/fd/ directory,
depending on the operating system. The command inside it is run in
the background, connected to the pipe/FD. The other end is available
to the shell. The first < redirects input from this pipe/FD.
See http://mywiki.wooledge.org/ProcessSubstitution for more details.
If you were writing this without bash, you could do something like:
#!/bin/sh
trap 'rm -f /tmp/foo$$' EXIT
process() {
...
}
mkfifo /tmp/foo$$
find . -type f -name '*-C.aif' > /tmp/foo$$ &
while IFS= read -r file; do
process "$file"
done < /tmp/foo$$
This would be nearly equivalent to the process substitution.
Note that non-bash shells don't have read -d '' so I had to drop the
NUL delimiter (-d '' and -print0), so this version won't handle filenames
that contain newlines. Only bash can do that correctly.
If you had to handle newlines without bash available, the best solution
would be to use -exec as I mentioned briefly before:
#!/bin/sh
find . -type f -name '*-C.aif' -exec sh -c '
for file; do
pre="${file%-C.aif}"
L="$pre-(L).aif"
...
ffmpeg -i "$L" -acodec ...
done
' _ {} +
I didn't give that answer the first time because it's the most cryptic,
but this is the most portable solution. You can see
http://mywiki.wooledge.org/UsingFind for explanations.