This can happen if the application is writing directly to the TTY instead of STDOUT or STDERR.
You can play with this behavior by comparing the 2 examples below
( echo foo ) &>/dev/null
( echo foo > $(tty) ) &>/dev/null
Notice the first doesn't show anything, but the second does. That's because we sent the output directly to the tty and bypassed the redirection to /dev/null
.
You can get around stuff like this by using script
script -c '( echo foo > $(tty) ) &>/dev/null' >/dev/null
Basically the script
utility creates a fake tty and launches the command in that tty. Any output from the command is sent to STDOUT which you can then redirect as normal.
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"
done
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"
done
Best Answer
Try this:
Passing
xargs
the-r
flag will cause it to only runbasename
if reads at least one item from standard input (head -1
).head -1
will run but you won't see or capture any output from it.Also, if you don't want the user to see any error output from
ls
, you can redirectls
's stderr stream to/dev/null
.Also note that I added quotation marks around
$MY_DIR
. That way, the command will not fail if$MY_DIR
contains spaces.If you're using a modern shell such as bash, you should use a
$( )
capture shell instead of backticks. You should also consider changing the style of your variables. You should generally avoid using all-uppercase variable names in scripts. That style is generally reserved for reserved and environmental variables.