# CLI is great - some early examples

**URL:** <https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170>\
**Category:** Code Sharing\
**Created:** [April 5, 2019, 3:23pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170 "2019-04-05T15:23:41Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![tremblap](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/tremblap/32/5_2.png) [@tremblap](https://discourse.flucoma.org/u/tremblap)\
**Post date:** [April 5, 2019, 3:23pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/1 "2019-04-05T15:23:42Z")

</div>

It seems @jamesbradbury is on fire. Early examples moved here from another thread to stay focus 😉

---

<div class="post-metadata">

**Author:** ![jamesbradbury](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/jamesbradbury/32/1252_2.png) [@jamesbradbury](https://discourse.flucoma.org/u/jamesbradbury)\
**Post date:** [April 5, 2019, 3:25pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/2 "2019-04-05T15:25:35Z")

</div>

Thanks PA! Copied here.

CLI is great.

I made two bash scripts that you can add to your `.bash_profile` . These do batch processing using nmf or hpss functions.

The two functions would then be called through your terminal of choice (assuming you are using bash and not zsh or fish or something) as `batch_nmf` and `batch_hpss` .

`batch_nmf` takes three arguments.  
1: Input Folder  
2: Output Folder  
3: Number of Ranks

The output of dog.wav would be dog-nmf.wav in your output folder.

`batch_hpss` takes two arguments  
1: Input Folder  
2: Output Folder

The output of cat.wav would be cat-h.wav and cat-p.wav in your output folder.

Code below. Enjoy!

```auto
### batch_hpss is passed two variables.

### Arg 1: Source Folder

### Arg 2: Output Folder

function batch_hpss () {

shopt -s nullglob

if [-d "$2"]; then

for src in $1/*;

do

                file_name=$(basename "$src")

                strip_ext=$(echo "$file_name" | cut -f 1 -d '.')

                harm_sf="$2/$strip_ext-h.wav"

                perc_sf="$2/$strip_ext-p.wav"

echo "Starting separation on $src"

                hpss -source $src -harmonic $harm_sf -percussive $perc_sf

echo "$src has been separated!"

echo "Output at $2_filename_p/h.wav"

done

echo "Finished batch hpss processing"

else

echo "The output directory does not exist."

echo "I have made it for you!"

echo "You will need to re-run the command in your shell."

        mkdir $2

fi

}

### batch_nmf is passed three variables.

### Arg 1: Source Folder

### Arg 2: Output Folder

### Arg 3: Number of NMF Ranks

function batch_nmf () {

shopt -s nullglob

if [-d "$2"]; then

for src in $1/*;

do

                file_name=$(basename "$src")

                strip_ext=$(echo "$file_name" | cut -f 1 -d '.') ## Remove extension

                out="$2/$strip_ext-nmf.wav" ## Make name for output

## Process ##

echo "Starting NMF on $src"

                nmf -source $src -rank $3 -resynth $out

echo "Completed NMF on $src"

echo "Output at $out"

done

echo "Finished batch nmf processing"

else

echo "The output directory does not exist."

echo "I have made it for you!"

echo "You will need to re-run the commannd in your shell."

        mkdir $2

fi

}

```

To clarify, you need to copy this code to your clipboard. Open up `terminal` go to your root directory and type `open .bash_profile`. If the file doesn’t exist type `touch .bash_profile`, then repeat the previous command. Once you’ve opened the `bash_profile` paste the contents of the clipboard into that file, save and close it. Run the command `. .bash_profile` or close and restart `terminal`. The commands should now work!

---

<div class="post-metadata">

**Author:** ![jamesbradbury](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/jamesbradbury/32/1252_2.png) [@jamesbradbury](https://discourse.flucoma.org/u/jamesbradbury)\
**Post date:** [April 5, 2019, 5:07pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/3 "2019-04-05T17:07:00Z")

</div>

Okay one more for fun.

This is a server in python that can dispatch asynchronous calls to your shell. A folder is watched for any files that are added to it and if it detects a new file it automatically calls the shell to run hpss on it. You can decide if you want the output to be relative to the file or in an absolute location. The best part is, you don’t have to wait for one process to finish before you add another file - you can just keep adding files to the folder and it will queue it up. The next stage is to make it run multiple processes simultaneously 🙂

This one isn’t super friendly if you haven’t used python before and I definitely haven’t tested it. It will try and hpss anything you put in the file, and there is no protections against this however the script probably wont execute which won’t stop the overall server from running.

This requires Python 3.6 and watchdog which can be installed with `pip install watchdog`

```auto
import logging
import sys
import time
import os
import subprocess

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

logging.basicConfig(level=logging.DEBUG)

class MyEventHandler(FileSystemEventHandler):
    def __init__ (self):
        self.creation_rule = ''
        self.file_name = ''
        self.only_file = ''
        self.dir_name = ''
        self.base = ''
        self.abs_dir = None

    def catch_all_handler(self, event):
        logging.debug(event)

    def on_moved(self, event):
        self.catch_all_handler(event)

    def on_created(self, event):
        self.catch_all_handler(event)
        self.file_name = str(event.src_path)
        self.base = os.path.basename(self.file_name)
        self.only_file = os.path.splitext(self.base)[0]

        if self.creation_rule == 'Relative':
            self.dir_name = f'{os.path.dirname(self.file_name)}/{self.only_file}_proc'
            try:
                os.makedirs(self.dir_name)
            except FileExistsError:
                print('Files possibly being overwritten or already exist')
                pass

        elif self.creation_rule == 'Absolute':
            self.dir_name = f'{self.abs_dir}/{self.only_file}_proc/'
            if self.abs_dir != None:
                try:
                    os.makedirs(self.dir_name)
                except FileExistsError:
                    print('Files possibly being overwritten or already exist')
                    pass

        cmd = ['hpss', '-source', self.file_name, '-harmonic', f'{self.dir_name}/{self.only_file}-harm.wav', '-percussive', f'{self.dir_name}/{self.only_file}-perc.wav']
        subprocess.call(cmd)

    def on_deleted(self, event):
        self.catch_all_handler(event)

    def on_modified(self, event):
        self.catch_all_handler(event)

### Set your path here that you want to watch. Make sure you leave the backslash off at the end
path = '/Users/jamesbradbury/dev'

event_handler = MyEventHandler()
event_handler.creation_rule = 'Absolute' ### You can set this string to 'Relative' or 'Absolute' to change how the output file structure works
event_handler.abs_dir = '/Users/jamesbradbury/_abs_processing'
observer = Observer()
observer.schedule(event_handler, path, recursive=False)
observer.start()
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    observer.stop()
observer.join()

```

---

<div class="post-metadata">

**Author:** ![tremblap](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/tremblap/32/5_2.png) [@tremblap](https://discourse.flucoma.org/u/tremblap)\
**Post date:** [April 5, 2019, 5:24pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/4 "2019-04-05T17:24:45Z")

</div>

oh la la, you’re on fire! I look forward to batch process some sounds now 😉

---

<div class="post-metadata">

**Author:** ![tremblap](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/tremblap/32/5_2.png) [@tremblap](https://discourse.flucoma.org/u/tremblap)\
**Post date:** [April 11, 2019, 8:47am UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/5 "2019-04-11T08:47:41Z")

</div>

Quick note: the arguments in the CLI are in line, spelling included, with the Max ones. (all lower case, not hard to guess from the SC helpfile) and the right format (for -fftsettings you need the 3 windowing arguments as one)

---

<div class="post-metadata">

**Author:** ![tutschku](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/tutschku/32/22_2.png) [@tutschku](https://discourse.flucoma.org/u/tutschku)\
**Post date:** [April 17, 2019, 9:21pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/6 "2019-04-17T21:21:07Z")

</div>

Just trying it, but getting syntax error messages. What is the right way of doing it?  
I tried the paths variables with no quotes, single quotes and double quotes, but none of them is accepted  
batch\_nmf("/Users/hans/Desktop/flucoma-input" “/Users/hans/Desktop/flucoma-output” 5)

-bash: syntax error near unexpected token `"/Users/hans/Desktop/flucoma-input"’

---

<div class="post-metadata">

**Author:** ![jamesbradbury](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/jamesbradbury/32/1252_2.png) [@jamesbradbury](https://discourse.flucoma.org/u/jamesbradbury)\
**Post date:** [April 21, 2019, 5:01pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/7 "2019-04-21T17:01:40Z")

</div>

I didn’t get a notification about this Hans, so I’m sorry for the delayed response.

The way that bash takes arguments is positional and with no brackets.

 ![image](https://discourse.flucoma.org/uploads/default/original/1X/71823b19a833c5846980b05152df30ae0d2578d2.png)

You can see in this example I have tried to run the batch process but the output folder isn’t made yet. Bash makes it for you with `mkdir` and then you can run the process again.

I’ve also uploaded a short video to clarify usage 🙂

https://player.vimeo.com/video/331677460?app_id=122963

If this is useful for you, I’ll add some more functionality to pass arguments in an easy way. Just let me know.

---

<div class="post-metadata">

**Author:** ![tutschku](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/tutschku/32/22_2.png) [@tutschku](https://discourse.flucoma.org/u/tutschku)\
**Post date:** [April 21, 2019, 6:20pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/8 "2019-04-21T18:20:43Z")

</div>

ok, that helpful  
I did the following steps from your earlier message  
hans$ open .bash\_profile  
I copied your code in there, saved, quit terminal, reopened.

But I’m still getting an error message:

MacBook-2018:~ hans$ pwd

/Users/hans

MacBook-2018:~ hans$ batch\_nmf ~/Desktop/flucoma-input ~/Desktop/flucoma-output 5

Starting NMF on /Users/hans/Desktop/flucoma-input/Oud-normal-Csharp3-ff.wav

-bash: nmf: command not found

Completed NMF on /Users/hans/Desktop/flucoma-input/Oud-normal-Csharp3-ff.wav

Output at /Users/hans/Desktop/flucoma-output/Oud-normal-Csharp3-ff-nmf.wav

Finished batch nmf processing

MacBook-2018:~ hans$

---

<div class="post-metadata">

**Author:** ![jamesbradbury](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/jamesbradbury/32/1252_2.png) [@jamesbradbury](https://discourse.flucoma.org/u/jamesbradbury)\
**Post date:** [April 21, 2019, 7:04pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/9 "2019-04-21T19:04:39Z")

</div>

Can you post the contents of your .bash\_profile here? I have a feeling I know what the problem is, but can’t confirm till I see. Another thing to check is can you do basic commands like `ls` and `cd`. If you can’t there is something wrong with your $PATH.

---

<div class="post-metadata">

**Author:** ![jamesbradbury](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/jamesbradbury/32/1252_2.png) [@jamesbradbury](https://discourse.flucoma.org/u/jamesbradbury)\
**Post date:** [April 21, 2019, 8:01pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/10 "2019-04-21T20:01:31Z")

</div>

Okay, so the bash\_profile is configured correctly that isn’t the issue. The problem is that you don’t have the flucoma stuff in your path somewhere and so when the bash script tells the shell to run nmf, it has no idea what you’re talking about.

Easiest way to add it to your shell is to put it somewhere you know it won’t move. Mine is in a folder close to my ~/ directory.

run `sudo nano /etc/paths` in your terminal, put in your password. A text editor will come up. Add a line at the bottom with the directory of the flucoma tools.

It should look something like this:

 ![image](https://discourse.flucoma.org/uploads/default/original/1X/0a5ee00f09e5b4bb285c7e64c682599ca6851b26.png)

You can see I have the CLI stuff in a folder called Fluid\_CLI.

Once you have put that directory in, Control + O then enter then restart your terminal. You then **should** be able to use the flucoma cli.

---

<div class="post-metadata">

**Author:** ![tutschku](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/tutschku/32/22_2.png) [@tutschku](https://discourse.flucoma.org/u/tutschku)\
**Post date:** [April 21, 2019, 10:14pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/11 "2019-04-21T22:14:57Z")

</div>

Genial! Thanks a lot for your trouble-shooting tips.

---

<div class="post-metadata">

**Author:** ![jamesbradbury](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/jamesbradbury/32/1252_2.png) [@jamesbradbury](https://discourse.flucoma.org/u/jamesbradbury)\
**Post date:** [April 21, 2019, 10:55pm UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/12 "2019-04-21T22:55:37Z")

</div>

I will assume this means its working for you 🙂

---

<div class="post-metadata">

**Author:** ![tremblap](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/tremblap/32/5_2.png) [@tremblap](https://discourse.flucoma.org/u/tremblap)\
**Post date:** [April 22, 2019, 9:30am UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/13 "2019-04-22T09:30:54Z")

</div>

Thanks for the film @jamesbradbury!

---

<div class="post-metadata">

**Author:** ![jamesbradbury](https://discourse.flucoma.org/user_avatar/discourse.flucoma.org/jamesbradbury/32/1252_2.png) [@jamesbradbury](https://discourse.flucoma.org/u/jamesbradbury)\
**Post date:** [May 21, 2019, 10:32am UTC](https://discourse.flucoma.org/t/cli-is-great-some-early-examples/170/14 "2019-05-21T10:32:07Z")

</div>

The original bash scripts I made were not very extensible. In particular, adding -parameters was proving very hacky and not very fluent. Every Mac (sorry windows users) comes with python 2 so I’ve made some scripts with this that can be used for batching some of the processes. At the moment this includes only nmf, but from the plenary there seems to be a lot of interest in this particular tool.

Usage is simple, put the scripts next to the executables and run them from them from your terminal.

# Example file structure:

 ![image](https://discourse.flucoma.org/uploads/default/original/1X/51352cece2e58db66e94669e88a098c7aa457915.png)

Really, the scripts can be anywhere. You just need to remember where you put them!

# Example usage:

First, you have to `cd` to the location of the scripts. I put mine next to the executables so lets go there in the terminal.

 ![image](https://discourse.flucoma.org/uploads/default/original/1X/b6eff586ac90c0d8d4df451c8578a85fbb7df0b5.png)

Then we call the script with some parameters. Note, the input and output parameters are _not_ the same as the original ones. We are dealing with input and output folders and the parameters reflect this as -input and -output.

 ![image](https://discourse.flucoma.org/uploads/default/original/1X/b22325c1c6ecfd5c19a7ad3f61953160e074383b.png)

Link to the scripts.

> **[jamesb93/Fluid\_CLI-Python-Scripts](https://github.com/jamesb93/Fluid_CLI-Python-Scripts)**
>
> Python Scripts for batch processing with the FluCoMA command line tools. - jamesb93/Fluid\_CLI-Python-Scripts

Any questions/suggestions, shoot!
