QGIS – Batch Processing Using Expressions: Renaming Output with Input Layer Name and Substring Modification in QGIS 3.16

batchexpressionlayer-namerename

I'd like to run different batch processes and want to name the output derived by the input layername with only changing one specific substring when doing batch processes.
I will conduct different batch-processes. You may assume raster/conversion/translate for this question. (<– As it seems to me the batch-processing-interface works always prinicipally the same way, right?)

First an excerpt of my TOC with short description of the naming system of the files I'dlike to batch-proceed:

enter image description here

  • RED: Tile location, derived from group name, always beginning with T, followed by two digits, underscore, again two digits as e.g. T11_09, T04_20
  • ORANGE: varying Sat-recording-date
  • YELLOW: no variance, substring is always LEVEL2
  • GREEN: Satellite, two options: SEN2A or SEN2B
  • BLUE: File content, no variance, always BOA
  • BLACK: up to 4 appendices containing different information, without a too strict system except from the underscore as delimiter

Maybe IMPORTANT!!!: RED to BLUE substrings correspond with the filename (source), whereas the BLACK substrings are only part of the layername.

Now, I want the output filenames to get the same name as the current input layernames (if not possible the source file name) BUT with changing the BOA-substring e.g. to RFC
Example:
T10_08_20181011_LEVEL2_SEN2B_BOA_N_LDm015_START2 to T10_08_20181011_LEVEL2_SEN2B_RFC_N_LDm015_START2

I guess I can only do this by using expressions, right?. But unfurtunately, I am not familiar to this expressions topic + in general quite new to QGIS. So, to be honest I didn't tried anything as I have not any idea where or how to start (except from getting a rough impression of the expressions-interface).
May anybody help me, please? At least with where to start or with telling me which expressions I need.

Maybe this plays also a role (I don't know, as I only used the 'basic' batch way yet, i.e. without expressions):
The output files should be written into a new extra directory (not in the input diretory).

Best Answer

If you use "Calculate by Expression" from the "Autofill" menu on the right-most column of the Batch Processing menu in a QGIS tool, there is a lot of flexibility in how you name the output files.

This expression would replace 'BOA' with 'RFC' in the input layer name, for batch processing tables which have one input layer per row:

concat(file_path(file_path(layer_property(@INPUT, 'path'))),
       '\\RFC_New\\',
       replace(layer_property(@INPUT, 'name'), 'BOA', 'RFC'),
       '.bmp')

Here, concat is being used to connect multiple expressions to create one file name for the output. The example above is assuming the new directory, which you will have to have already created, is under the parent directory of the input file directory. layer_property(@INPUT, 'path') gets the full path of the input layer including the file name. file_path is wrapped around this in order to get the path just for the directory containing the file, and then file_path is wrapped around that again to get the parent directory. Hopefully from this you can sort of see how you could construct the file path to a directory of your choosing relative to the existing file structure in the project.

After the first comma, \\RFC_New\\ is a name I made up for the new directory you would create beforehand; it could be replaced with whatever you would like to call it as long as it already exists on the file system. This gets appended to the file path of the parent directory which was just constructed.

Then, layer_property(@INPUT, 'name') gets the name of the input layer you see within QGIS. replace(layer_property(@INPUT, 'name'), 'BOA', 'RFC') is replacing any instance of the string 'BOA' with 'RFC'. Finally, '.bmp' at the end of the expression is an example file extension; it would be whichever format is appropriate for your batch process.

Here is the same expression, but for replacing the input layer file name (one input layer per row):

concat(file_path(file_path(layer_property(@INPUT, 'path'))),
       '\\RFC_New\\',
       replace(base_file_name(layer_property(@INPUT, 'path')), 'BOA', 'RFC'),
       '.bmp')

base_file_name is used to get just the name in the file without the extension from the 'path' of the input layer.

As a final example, here is how you might construct an expression for the output for processes where each row has multiple input layers.

array_foreach(@LAYERS,
  concat(file_path(file_path(layer_property(@element, 'path'))),
         '\\RFC_New\\',
         replace(base_file_name(layer_property(@element, 'path')),
                 'BOA', 'RFC'),
         '.bmp')
)

In these instances, the inputs are set to an array variable @LAYERS which contains multiple layer IDs for each row. array_foreach iterates over every item within an array to construct a new one, with @element representing a single item within the array for each iteration. So in this case, for each of the input @LAYERS within one row, the file path will be constructed based on the layer name, and then added to a list of new layer file names and paths which will become the output for that row.

Related Question