I'm trying to automatically convert flac files moved to a folder into mp3 in another folder.

My current line of code is this:

inotifywait -m -r -q -e moved_to --format "'%w%f'" ~/test |  xargs -I x flac -cd x - | lame -b 320 - /media/1tb/x.mp3

To explain how this works so far, inotifywait monitors ~/test recursively for files moved there, outputting the path and filename to a pipe. xargs takes that name and creates the proper flac command, replacing x with the filename and decoding the file to another pipe. In the new pipe lame processes the output of flac into mp3 under /media. I want xargs to either reach across the pipe in some way, replacing the x in the lame command or in some way send it to a variable both commands can access or something. I tried messing around with named pipes and that jazz but the fact that there is actual data being piped between the two commands has me in way over my head.

2 Answers 2


If I understand correctly, you want to fire up one instance flac … | lame … for each input line, and interpolate the input into the arguments to both commands.

Since you need xargs to start a pipeline, you need to make it start a program that's capable of creating pipelines, i.e. a shell.

inotifywait -m -r -q -e moved_to --format "%w%f" ~/test |
xargs -l sh -c 'flac -cd "$0" - | lame -b 320 - "/media/1tb/$0.mp3"'

Alternatively, have the calling shell read lines one by one and run the pipeline.

inotifywait -m -r -q -e moved_to --format "%w%f" ~/test |
while IFS= read -r file; do
  flac -cd "$file" - | lame -b 320 - "/media/1tb/$file.mp3"

Note that the format %w%f produces an absolute path, to which you're prepending /media/1tb and appending .mp3. If you want to strip off the directory part of the file in the lame command, change $file to ${file##*/}. If you want to strip off the extension, change $file to ${file%.*}. If you want to do both, you'll have to do it in two steps. If you want to reproduce the directory hierarchy under /media/1tb, you can use mkdir -p.

cd ~/test
inotifywait -m -r -q -e moved_to --format "%w%f" . |
while IFS= read -r file; do
  [ -f "$file" ] || continue; # skip directories and other special files
  dir=${file%/*}; file=${file##*/}
  mkdir -p "/media/1tb/$dir"
  flac -cd "$dir/$file" - | lame -b 320 - "/media/1tb/$dir/${file#.*}.mp3"

You could try something like:

inotifywait -m -r -q -e moved_to --format "'%w%f'" ~/test \
    | while read x; do \
        flac -cd "$x" - | lame -b 320 - "/media/1tb/$x.mp3"
  • 1
    while read … is a solution, but then, drop xargs. What you wrote just doesn't make sense: where do you think xargs is getting its input? And you should quote things properly, it's common for music file names to contain spaces. Dec 23, 2013 at 1:33
  • @Gilles It wasn't/isn't clear to me exactly what the OP is doing, which is why I said "you could try something like" and "I'm not sure if the xargs bit is true to your intentions" etc. So not the best answer but a hint in the right direction, I think. Have fixed the quoting issue and removed xargs.
    – goldilocks
    Dec 23, 2013 at 12:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.