Files & Directories
So far, our scripts were able to manage individual files. But scripts are particularly useful for batch processing of many files, e.g. all wav files in a given directory. Batch processing is applicable with and without user interaction. For instance, a script can incrementally read files from a target directory, open every file in an editor, wait for the user to do something (e.g. an annotation), finish off with some post-processing, and load the next file. Or a script may ask the user for a target directory and then process all files without further interaction (e.g. calculating pitch parameters), presenting results in Praat Info. Or a standard directory is declared in the script, so that the script processes files autonomously without any interaction as soon as it is launched.
The standard procedure for Praat batch processing consists of two steps: (1) Create a list of all target files (the dedicated container for file lists is a Strings object). (2) Loop through the file list, incrementally processing file after file.
Listing and filtering files
Step 1 is implemented using the GUI command
Create Strings as file list... (located in the
New menu of Praat Objects). As the name suggests, the command creates a Strings object containing a list of filenames, one filename per line.
Create Strings as file list has two arguments: a name for the newly created Strings object and a file specification. The only idiosyncrasy concerning object naming is the replacement of spaces with underscores, other than that there's nothing to bear in mind. The file specification argument is more interesting:
- If only a directory path is given, all files in the specified directory will be part of the list.
- If a full file specification is given, only the one specified file is listed—which is useless, you don't need a list for one file…
- Instead of listing all files or only one file, the range of target files can be restricted with a wildcard: The asterisk (*) is a joker matching any character. It is used to define filename patterns. Only one wildcard is permitted. Some examples:
|*.wav||all filenames ending with .wav|
|recording*||all filenames starting with recording|
|item*.wav||all filenames starting with item and ending with .wav|
|item*.*||all filenames starting with item, followed by any number of arbitrary characters, followed by .* → Only the first asterisk is interpreted as a wildcard, additional asterisks are interpreted as literal characters!|
Lists created with
Create Strings as file list contain only filenames, the path information is not part of the list!
To practice file list creation and become familiar with filename patterns using a wildcard, select
New > Create Strings as file list..., try different patterns in the File path input field, click apply, and review the resulting list with
View & Edit.
Having unraveled the mechanism of file list creation, implementation is straightforward:
Create Strings as file list: "Filelist", "*.wav"
- creates a Strings object called Filelist
- containing a list of all filenames ending with .wav
- of files located in the working directory.
Step 2 of batch processing involves looping through the file list which we created in step 1. We have to put off implementation of this step until we finish discussing loops in the next session. What we can do now, however, is pondering over an abstract algorithm, so that the structure of the script is ready for implementation as soon as we're able to use loops. What we have: A list of filenames, referencing files in a given directory. What we need: Incremental processing of all files referenced in the file list.
First the number of filenames in the list must be determined to find out the number of passes through the loop. Then the loop is set up. It provides an index, starting with 1, which is incremented by 1 until the number of files is reached, i.e. until all files in the list are processed. Within the loop, the filename with the current index is pulled from the list, then the referenced file is loaded, processed, and removed:
create file list n = determine number of files to process start loop with i = 1 extract filename[i] from file list (first, second, third, ..., last) load file[i] as object statement 3 statement 4 statement 5 ... remove object[i] increment i by 1 end loop if i = n remove file list
This, of course, is not valid Praat scripting code, it's just an outline of what we want our script to do. It's formulated in 'code-aware', i.e. formalized natural language and is a good exercise in 'algorithmic thinking'.
To handle files (open/save), standard menu commands may be used. To provide the script user with the familiar graphical file selection dialogue, use special choose functions.
Standard string operators and functions are flexible and powerful tools to assemble (and evaluate) file specifications in a script. Save commands in scripts overwrite existing files without warning. With
fileReadable (), Praat provides a sufficient (if not bullet-proof) method to check for existing files before saving.
Creating filename lists is a prerequisite of batch processing. Use of the wildcard "*" (asterisk) allows the definition of filename patterns to restrict file selection.