help-bash
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]