If you are open to a PyQGIS solution, it can be done very simply:
p = QgsProject.instance()
# get all layers in project
lyrs = p.mapLayers().values()
# filter layers if necessary (could also filter by geometry type)
line_layers = [x for x in lyrs if 'line' in x.name().lower()]
# merge layers (don't forget to specify your coordinate system)
merged = processing.run("native:mergevectorlayers", {'LAYERS':line_layers,'CRS':QgsCoordinateReferenceSystem('EPSG:4326'),'OUTPUT':'TEMPORARY_OUTPUT'})['OUTPUT']
# add to canvas
p.addMapLayer(merged)
To merge layers per group (using the hierarchy in your screenshot):
# reference to the project
p = QgsProject.instance()
# reference to the layer tree
root = p.layerTreeRoot()
# reference to the group called 'Batch'
group = root.findGroup('Batch')
# loop through all the items in the Batch group
for child in group.children():
# find sub-groups
if isinstance(child, QgsLayerTreeGroup):
sub_group = child
# empty list to store the layers ready to merge
lyrs_to_merge = []
# find line layers in the sub-group
for sub_child in sub_group.children():
# check whether the child is a layer and has 'line' in its name
if isinstance(sub_child, QgsLayerTreeLayer) and 'line' in sub_child.name().lower():
lyr = sub_child
# add to list
lyrs_to_merge.append(lyr.layerId())
# perform merge
merged = processing.run("native:mergevectorlayers", {'LAYERS':lyrs_to_merge,'CRS':QgsCoordinateReferenceSystem('EPSG:4326'),'OUTPUT':'TEMPORARY_OUTPUT'})['OUTPUT']
# name the merged layer
merged.setName('merged | ' + sub_group.name())
# add layer to project, but prevent adding to canvas and layer tree (with False)
p.addMapLayer(merged, False)
# insert the merged layer at the top of each sub-group
sub_group.insertLayer(0, merged)
Result: