Major update to merge-tagfiles.

This commit is contained in:
Darren 'Tadgy' Austin 2026-05-12 23:27:31 +01:00
commit f66d2ff96d

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# Version: 0.0.1 # Version: 0.2.0
# Copyright (c) 2017: # Copyright (c) 2017-2026:
# Darren 'Tadgy' Austin <darren (at) afterdark.org.uk> # Darren 'Tadgy' Austin <darren (at) afterdark.org.uk>
# Licensed under the terms of the GNU General Public License version 3. # Licensed under the terms of the GNU General Public License version 3.
# #
@ -10,21 +10,36 @@
# The (space separated) list of package sets. # The (space separated) list of package sets.
PACKAGE_SETS="${PACKAGE_SETS:-a ap d e f k kde kdei l n t tcl x xap xfce y}" PACKAGE_SETS="${PACKAGE_SETS:-a ap d e f k kde kdei l n t tcl x xap xfce y}"
# nullglob is required.
shopt -s nullglob
#........1.........2.........3.........4.........5.........6.........7.........8.........9.........0.........1.........2.........3.....:...4 # Functions.
display_help() { display_help() {
# |--------1---------2---------3---------4---------5---------6---------7---------8 # |--------1---------2---------3---------4---------5---------6---------7---------8
echo "Usage: ${0##*/} [options] <tagfiles dir1> <tagfiles dir2> <dest dir>" echo "Usage: ${0##*/} [options] <tagfiles dir1> <tagfiles dir2> <dest dir>"
echo "Automatically or interactively merge tagfiles from <tagfiles dir1> and" echo "Automatically or interactively merge tagfiles from <tagfiles dir1> and"
echo "<tagfiles dir2>, writing the resultant tagfile set to <dest dir>. Priorities " echo "<tagfiles dir2>, writing the resultant tagfile set to <dest dir>."
echo "from <tagfiles dir2> take presidence over those in <tagfiles dir1>." echo
echo "Caveats:"
echo " * Priorities from <tagfiles dir2> sets take presidence over <tagfiles dir1>."
echo " * Only the packages listed in the <tagfiles dir1> sets are merged with the"
echo " priorities from the <tagfiles dir2> sets - packages in the <tagfiles dir2>"
echo " sets not in the <tagfiles dir1> set are removed in the <dest dir> sets."
echo " * Package descriptions are read from .txt files in either <tagfiles dir1> or"
echo " <tagfiles dir2>, whichever directory contains the file first."
# echo " * Only comments from <tagfiles dir2> sets are merged into <dest dir> sets."
echo echo
echo "Options:" echo "Options:"
echo " -a, --default-add Do not interactively prompt whether to ADD or SKP any new" echo " -a, --default-add Do not interactively prompt whether to ADD, REC, SKP or OPT"
echo " packages in <tagfile dir1>; automatically use this default." echo " any new packages - automatically use this default."
echo " -r, --default-rec See above."
echo " -s, --default-skp See above." echo " -s, --default-skp See above."
echo " -v, --version Display version and copyright information." echo " -o, --default-opt See above."
echo " -n, --no-recopt Only allow the ADD or SKP priorities. In interactive mode"
echo " the replacement priority is prompted for, otherwise the"
echo " options --default-add or --default-skp determine priority."
echo " -N, --no-desc Do not show the package description in interactive mode."
echo " -V, --version Display version and copyright information."
echo " -h, --help Display this help, obviously." echo " -h, --help Display this help, obviously."
echo " -- Force the end of option processing. Any options following" echo " -- Force the end of option processing. Any options following"
echo " this are treated as arguments." echo " this are treated as arguments."
@ -33,14 +48,14 @@ display_help() {
echo "Arguments (all of which are mandatory):" echo "Arguments (all of which are mandatory):"
echo " <tagfiles dir1> The top-level directory of the first set of tagfiles." echo " <tagfiles dir1> The top-level directory of the first set of tagfiles."
echo " <tagfiles dir2> The top-level directory of the second set of tagfiles." echo " <tagfiles dir2> The top-level directory of the second set of tagfiles."
echo " <dest dir> Path to the directory in which to write the new tagfiles." echo " <dest dir> Path to the directory in which to write the new tagfiles."
return 0 return 0
} }
display_version() { display_version() {
# |--------1---------2---------3---------4---------5---------6---------7---------8 # |--------1---------2---------3---------4---------5---------6---------7---------8
echo "${0##*/} v0.0.1" echo "${0##*/} v0.2.0"
echo "Copyright (c) 2017 Darren 'Tadgy' Austin <darren (at) afterdark.org.uk>" echo "Copyright (c) 2017-2026 Darren 'Tadgy' Austin <darren (at) afterdark.org.uk>"
echo "Licensed under the terms of the GNU GPL v3 <http://gnu.org/licenses/gpl.html>." echo "Licensed under the terms of the GNU GPL v3 <http://gnu.org/licenses/gpl.html>."
echo "This program is free software: you can modify or redistribute it in accordence" echo "This program is free software: you can modify or redistribute it in accordence"
echo "with the GNU GPL. However, it comes with ABSOLUTELY NO WARRANTY; not even the" echo "with the GNU GPL. However, it comes with ABSOLUTELY NO WARRANTY; not even the"
@ -49,12 +64,12 @@ display_version() {
} }
check_directory() { check_directory() {
# Params: $1 = Directory to check. # Arguments: $1 = Directory to check.
# Returns: 0 = OK. # Returns: 0 = OK.
# 1 = Doesn't exist. # 1 = Doesn't exist.
# 2 = Not a directory. # 2 = Not a directory.
# 3 = No read permission. # 3 = No read permission.
# 4 = No write permission. # 4 = No write permission.
if [[ ! -e "$1" ]]; then if [[ ! -e "$1" ]]; then
echo "${0##*/}: no such directory: $1" >&2 echo "${0##*/}: no such directory: $1" >&2
return 1 return 1
@ -72,40 +87,68 @@ check_directory() {
} }
write_line() { write_line() {
# Params: $1 = Package. # Arguments: $1 = The package name.
# $2 = Priority. # $2 = The packages priority.
# $3 = Comment. # $3 = The packages comment.
# $4 = File to write to. # $4 = File to write to.
if [[ ! -z "$3" ]]; then if [[ ! -z "$3" ]]; then
printf "%s:%s\t\t%s\n" "$1" "$2" "$3" >>$4 || exit 1 printf "%s:%s\\t\\t%s\\n" "$1" "$2" "$3" >>"$4" || exit 1
else else
printf "%s:%s\n" "$1" "$2" >>$4 || exit 1 printf "%s:%s\\n" "$1" "$2" >>"$4" || exit 1
fi fi
} }
prompt_priority() { prompt_priority() {
# Params: $1 = Package. # Arguments: $1 = Package name being processed.
# $2 = Priority. # $2 = Previous priority of package being processed.
# $3 = Comment. # $3 = Any comment from the tagfile for the package.
# Variables: Modifies NEWPRI variable. # Globsl variables: SET = The tagfile set being processed.
# TAGFILES_DIR1 = The first tagfiles directory given on the command line.
# TAGFILES_DIR2 = The second tagfiles directory given on the command line.
# Returns: The new priority for the package.
local ANSWER DESC
local -a DESCFILE
FLAG_MANUAL_INPUT=1
echo echo
echo echo
echo "Package: $1" >&1 echo "Package: $SET/$1:"
echo "Current priority: ${2:-(none)}" [[ ! -v FLAG_NO_DESC ]] && {
echo "Comment: ${3:-(none)}" DESCFILE=( "$TAGFILES_DIR1/$SET/$1"-*-*-*.txt "$TAGFILES_DIR2/$SET/$1"-*-*-*.txt )
echo DESC="$(grep "^$1:" "${DESCFILE[0]}" 2>/dev/null | sed -re 's/^.*:[[:blank:]]*/ /g; s/^[[:blank:]]*$/ ./g')"
if [[ -n "$DESC" ]]; then
echo " Description from ${DESCFILE[0]}:"
echo "$DESC"
else
echo " Description not found."
fi
}
echo " Current priority: ${2:-(none)}"
echo " Comment: ${3:-(none)}"
local ANSWER
while :; do while :; do
read -r -n 1 -p "Select new tag for package: (A)DD or (S)KP: " ANSWER echo
if [[ -v FLAG_NO_RECOPT ]]; then
read -r -n 1 -p " Select new priority for package: (A)DD, or (S)KP: " ANSWER
else
read -r -n 1 -p " Select new priority for package: (A)DD, (R)EC, (S)KP, or (O)PT: " ANSWER
fi
if [[ "${ANSWER^^}" = "A" ]]; then if [[ "${ANSWER^^}" = "A" ]]; then
NEWPRI="ADD" NEWPRI="ADD"
break break
elif [[ ! -v FLAG_NO_RECOPT ]] && [[ "${ANSWER^^}" = "R" ]]; then
NEWPRI="REC"
break
elif [[ "${ANSWER^^}" = "S" ]]; then elif [[ "${ANSWER^^}" = "S" ]]; then
NEWPRI="SKP" NEWPRI="SKP"
break break
elif [[ ! -v FLAG_NO_RECOPT ]] && [[ "${ANSWER^^}" = "O" ]]; then
NEWPRI="OPT"
break
else else
continue continue
fi fi
@ -114,32 +157,53 @@ prompt_priority() {
process_tagfile() { process_tagfile() {
# Params: $1 = Input tagfile # Arguments: $1 = The tagfiles path to process.
# $2 = Output tagfile #
# Globsl variables: DEST_DIR = The destination directory to write the new tagfiles.
# SET = The tagfile set being processed.
local COMMENT NEWPRI PACKAGE PRIORITY
# Clear the destination tagfile. # Clear the destination tagfile.
: >$2 : >"$DEST_DIR/$SET/tagfile"
# Open the input tagfile for reading. # Open the input tagfile for reading.
# Note: We do this with an fd so we can use another 'read' of stdin for prompting. # Note: We do this with an fd so we can use another 'read' of stdin for prompting.
exec {FD}<"$1" exec {FD}<"$1/$SET/tagfile"
# Process the tagfile line by line. # Process the tagfile line by line.
local PACKAGE PRIORITY COMMENT NEWPRI
while IFS=$'\t :' read -r -u "$FD" PACKAGE PRIORITY COMMENT; do while IFS=$'\t :' read -r -u "$FD" PACKAGE PRIORITY COMMENT; do
if [[ "${PRIORITY^^}" = "ADD" || "${PRIORITY^^}" = "SKP" ]]; then if [[ -v FLAG_NO_RECOPT ]] && [[ ! "${PRIORITY^^}" =~ ^(ADD|SKP)$ ]]; then
# ADD or SKP. # Can't use REC or OPT - Get for new priority.
write_line "$PACKAGE" "${PRIORITY^^}" "$COMMENT" "$2" if [[ -v DEFAULT_PRIORITY ]]; then
else NEWPRI="$DEFAULT_PRIORITY"
# REC or OPT
if [[ ! -z "$DEFAULT_PRIORITY" ]]; then
# Use default priority.
write_line "$PACKAGE" "$DEFAULT_PRIORITY" "$COMMENT" "$2"
else else
# Prompt for new priority. prompt_priority "$PACKAGE" "${PRIORITY^^}" "$COMMENT" # Sets the NEWPRI variable
prompt_priority "$PACKAGE" "${PRIORITY^^}" "$COMMENT" # Has modified the NEWPRI variable
write_line "$PACKAGE" "$NEWPRI" "$COMMENT" "$2"
fi fi
[[ -z "$NEWPRI" ]] && {
echo "Abort: failed to get new priority" >&2
exit 1
}
write_line "$PACKAGE" "$NEWPRI" "$COMMENT" "$DEST_DIR/$SET/tagfile"
elif [[ "${PRIORITY^^}" =~ ^(ADD|SKP)$ ]]; then
# ADD or SKP in tagfile - write it out.
write_line "$PACKAGE" "${PRIORITY^^}" "$COMMENT" "$DEST_DIR/$SET/tagfile"
else
echo "** Invalid priority ($PRIORITY) for $PACKAGE in tagfile:"
echo "** $1/$2/tagfile"
# Invalid priority in tagfile - try to fix.
if [[ -v DEFAULT_PRIORITY ]]; then
echo "** Correcting using default priority: $DEFAULT_PRIORITY"
NEWPRI="$DEFAULT_PRIORITY"
else
echo "** Prompting for new valid priority..."
prompt_priority "$PACKAGE" "${PRIORITY^^}" "$COMMENT" # Sets the NEWPRI variabl
fi
[[ -z "$NEWPRI" ]] && {
echo "Abort: failed to get new priority" >&2
exit 1
}
write_line "$PACKAGE" "$NEWPRI" "$COMMENT" "$DEST_DIR/$SET/tagfile"
fi fi
done done
@ -148,69 +212,119 @@ process_tagfile() {
} }
merge_tagfiles() { merge_tagfiles() {
# Params: $1 = Tagfile 1 # Globsl variables: DEST_DIR = The destination directory to write the new tagfiles.
# $2 = Tagfile 2 # SET = The tagfile set being processed.
# $3 = Output tagfile # TAGFILES_DIR1 = The first tagfiles directory given on the command line.
# TAGFILES_DIR2 = The second tagfiles directory given on the command line.
local COMMENT1 COMMENT2 PACKAGE NEWPRI PRIORITY1 PRIORITY2
# Open the first tagfile for reading. # Open the first tagfile for reading.
# Note: We do this with an fd so we can use another 'read' of stdin for prompting. # Note: We do this with an fd so we can use another 'read' of stdin for prompting.
exec {FD}<"$1" exec {FD}<"$TAGFILES_DIR1/$SET/tagfile"
local PACKAGE1 PRIORITY1 COMMENT1 PACKAGE2_RHS NEWPRI
while IFS=$'\t :' read -r -u "$FD" PACKAGE1 PRIORITY1 COMMENT1; do
PRIORITY2="$(egrep "^${PACKAGE1//+/\\+}:" "$2" | cut -d: -f2- | sed -re 's/[[:blank:]]+.*$//')"
COMMENT2="$(egrep "^${PACKAGE1//+/\\+}:" "$2" | cut -d: -f2- | sed -re 's/(ADD|SKP|REC|OPT)//')"
while IFS=$'\t :' read -r -u "$FD" PACKAGE PRIORITY1 COMMENT1; do
PRIORITY2="$(grep -E "^${PACKAGE//+/\\+}:" "$TAGFILES_DIR2/$SET/tagfile" | sed -re "/^${PACKAGE//+/\\\+}:/ s/[^[:blank:]:]+:[[:blank:]]*([^[:blank:]]+)(\$|[[:blank:]].*\$)/\\1/")"
COMMENT2="$(grep -E "^${PACKAGE//+/\\+}:" "$TAGFILES_DIR2/$SET/tagfile" | sed -re "/^${PACKAGE//+/\\\+}:/ s/[^[:blank:]:]+:[[:blank:]]*([^[:blank:]]+)(\$|[[:blank:]](.*)\$)/\\3/")"
if [[ -z "$PRIORITY2" ]]; then if [[ -z "$PRIORITY2" ]]; then
# Package wasn't in tagfile2. # Package wasn't in tagfile2.
if [[ ! -z "$DEFAULT_PRIORITY" ]]; then if [[ ! -z "$DEFAULT_PRIORITY" ]]; then
# Use default priority. # Use default priority.
write_line "$PACKAGE1" "$DEFAULT_PRIORITY" "" "$3" write_line "$PACKAGE" "$DEFAULT_PRIORITY" "$COMMENT1" "$DEST_DIR/$SET/tagfile"
else else
# Prompt for new priority. # Prompt for new priority.
prompt_priority "$PACKAGE1" "${PRIORITY1^^}" "$COMMENT1" # Has modified the NEWPRI variable prompt_priority "$PACKAGE" "$PRIORITY1" "$COMMENT1" # Sets the NEWPRI variabl
write_line "$PACKAGE1" "$NEWPRI" "$COMMENT1" "$3" [[ -z "$NEWPRI" ]] && {
echo "Abort: failed to get new priority" >&2
exit 1
}
write_line "$PACKAGE" "$NEWPRI" "$COMMENT1" "$DEST_DIR/$SET/tagfile"
fi fi
elif ! [[ "${PRIORITY2^^}" =~ ^(ADD|SKP|REC|OPT) ]]; then elif [[ ! "${PRIORITY2^^}" =~ ^(ADD|REC|SKP|OPT) ]]; then
# Package was listed in tagfile2, but priority is invalid. # Package was listed in tagfile2, but priority is invalid.
if [[ ! -z "$DEFAULT_PRIORITY" ]]; then if [[ ! -z "$DEFAULT_PRIORITY" ]]; then
# Use default priority. # Use default priority.
write_line "$PACKAGE1" "$DEFAULT_PRIORITY" "" "$3" write_line "$PACKAGE" "$DEFAULT_PRIORITY" "${COMMENT2:-$COMMENT1}" "$DEST_DIR/$SET/tagfile"
else else
# Prompt for new priority. # Prompt for new priority.
prompt_priority "$PACKAGE1" "${PRIORITY2^^} (invalid)" "$COMMENT2" # Has modified the NEWPRI variable prompt_priority "$PACKAGE" "$PRIORITY2" "${COMMENT2:-$COMMENT1}" # Sets the NEWPRI variabl
write_line "$PACKAGE1" "$NEWPRI" "$COMMENT2" "$3" [[ -z "$NEWPRI" ]] && {
echo "Abort: failed to get new priority" >&2
exit 1
}
write_line "$PACKAGE" "$NEWPRI" "${COMMENT2:-$COMMENT1}" "$DEST_DIR/$SET/tagfile"
fi fi
else else
# Package was listed in tagfile2 and priority was valid. # Package was listed in tagfile2 and priority was valid.
write_line "$PACKAGE1" "${PRIORITY2^^}" "$COMMENT2" "$3" write_line "$PACKAGE" "${PRIORITY2^^}" "${COMMENT2:-$COMMENT1}" "$DEST_DIR/$SET/tagfile"
fi fi
done done
} }
# Process command line options. # Process command line options.
while :; do while :; do
case "$1" in case "$1" in
'-a'|'-default-add'|'--default-add') '-a'|'-default-add'|'--default-add')
if [[ "$DEFAULT_PRIORITY" = "SKP" ]]; then if [[ "$DEFAULT_PRIORITY" =~ ^(REC|SKP|OPT)$ ]]; then
echo "${0##*/}: options '$1' and '-s|--default-skp' are incompatible" >&2 echo "${0##*/}: multiple --default-* options specified" >&2
exit 1 exit 1
else else
DEFAULT_PRIORITY="ADD" DEFAULT_PRIORITY="ADD"
fi fi
shift shift
;; ;;
'-r'|'-default-rec'|'--default-rec')
[[ -v FLAG_NO_RECOPT ]] && {
echo "${0##*/}: cannot use --no-recopt with --default-rec" >&2
exit 1
}
if [[ "$DEFAULT_PRIORITY" =~ ^(ADD|SKP|OPT)$ ]]; then
echo "${0##*/}: multiple --default-* options specified" >&2
exit 1
else
DEFAULT_PRIORITY="REC"
fi
shift
;;
'-s'|'-default-skp'|'--default-skp') '-s'|'-default-skp'|'--default-skp')
if [[ "$DEFAULT_PRIORITY" = "ADD" ]]; then if [[ "$DEFAULT_PRIORITY" =~ ^(ADD|REC|OPT)$ ]]; then
echo "${0##*/}: options '$1' and '-a|--default-add' are incompatible" >&2 echo "${0##*/}: multiple --default-* options specified" >&2
exit 1 exit 1
else else
DEFAULT_PRIORITY="SKP" DEFAULT_PRIORITY="SKP"
fi fi
shift shift
;; ;;
'-v'|'-version'|'--version') '-o'|'-default-opt'|'--default-opt')
[[ -v FLAG_NO_RECOPT ]] && {
echo "${0##*/}: cannot use --no-recopt with --default-opt" >&2
exit 1
}
if [[ "$DEFAULT_PRIORITY" =~ ^(ADD|REC|SKP)$ ]]; then
echo "${0##*/}: multiple --default-* options specified" >&2
exit 1
else
DEFAULT_PRIORITY="OPT"
fi
shift
;;
'-n'|'-no-recopt'|'--no-recopt')
if [[ "$DEFAULT_PRIORITY" = "REC" ]]; then
echo "${0##*/}: cannot use --no-recopt with --default-rec" >&2
exit 1
elif [[ "$DEFAULT_PRIORITY" = "OPT" ]]; then
echo "${0##*/}: cannot use --no-recopt with --default-opt" >&2
exit 1
else
FLAG_NO_RECOPT=1
fi
shift
;;
'-N'|'-no-desc'|'--no-desc')
FLAG_NO_DESC=1
shift
;;
'-V'|'-version'|'--version')
display_version display_version
exit 0 exit 0
;; ;;
@ -242,12 +356,12 @@ done
echo "Try: ${0##*/} --help" >&2 echo "Try: ${0##*/} --help" >&2
exit 1 exit 1
} }
for ARG in $*; do for ARG in "$@"; do
ERROR_TEXT="$(check_directory "$ARG" 2>&1)" ERROR_TEXT="$(check_directory "$ARG" 2>&1)"
ERROR_CODE=$? ERROR_CODE=$?
if [[ -z "$TAGFILES_DIR1" || -z "$TAGFILES_DIR2" ]]; then if [[ -z "$TAGFILES_DIR1" || -z "$TAGFILES_DIR2" ]]; then
# <tagfiles dir1> and <tagfiles dir2> # <tagfiles dir1> and <tagfiles dir2>
if (( $ERROR_CODE >= 1 && $ERROR_CODE <= 3 )); then # Ignore write permission failure. if (( ERROR_CODE >= 1 && ERROR_CODE <= 3 )); then # Ignore write permission failure.
echo "$ERROR_TEXT" >&2 echo "$ERROR_TEXT" >&2
exit 1 exit 1
else else
@ -256,7 +370,7 @@ for ARG in $*; do
fi fi
else else
# <dest dir> # <dest dir>
if (( $ERROR_CODE >= 2 )); then # Non-existant (ERROR_CODE=1) is OK here. if (( ERROR_CODE >= 2 )); then # Non-existant (ERROR_CODE=1) is OK here.
echo "$ERROR_TEXT" >&2 echo "$ERROR_TEXT" >&2
exit 1 exit 1
else else
@ -274,31 +388,33 @@ if [[ -e "$DEST_DIR" ]]; then
echo "${0##*/}: directory exists: $DEST_DIR" >&2 echo "${0##*/}: directory exists: $DEST_DIR" >&2
exit 1 exit 1
else else
# shellcheck disable=SC2174
mkdir -p -m 755 "$DEST_DIR" || exit 1 mkdir -p -m 755 "$DEST_DIR" || exit 1
fi fi
# Main loop. # Main loop.
FLAG_MANUAL_INPUT=0
for SET in $PACKAGE_SETS; do for SET in $PACKAGE_SETS; do
mkdir "$DEST_DIR/$SET" || exit 1 mkdir "$DEST_DIR/$SET" || exit 1
if [[ ! -e "$TAGFILES_DIR1/$SET" ]]; then if [[ -e "$TAGFILES_DIR1/$SET/tagfile" ]]; then
# No tagfile in dir1. # Found tagfile in dir1.
if [[ -e "$TAGFILES_DIR2/$SET" ]]; then if [[ -e "$TAGFILES_DIR2/$SET/tagfile" ]]; then
# Found tagfiles in both dirs - merge the tagfiles into dest dir.
merge_tagfiles
else
# Process tagfile in dir1 and write to dest dir.
process_tagfile "$TAGFILES_DIR1" || exit 1
fi
else
# No tagfile in dir1 - check dir2.
if [[ -e "$TAGFILES_DIR2/$SET/tagfile" ]]; then
# Found tagfile in dir2 - process it and write to dest dir. # Found tagfile in dir2 - process it and write to dest dir.
process_tagfile "$TAGFILES_DIR2/$SET/tagfile" "$DEST_DIR/$SET/tagfile" || exit 1 process_tagfile "$TAGFILES_DIR2" || exit 1
else else
# No tagfile in either dir - create a stub file. # No tagfile in either dir - create a stub file.
touch "$DEST_DIR/$SET/tagfile" || exit 1 touch "$DEST_DIR/$SET/tagfile" || exit 1
fi fi
else
# Found tagfile in dir1.
if [[ ! -e "$TAGFILES_DIR2/$SET" ]]; then
# Process tagfile in dir1 and write to dest dir.
process_tagfile "$TAGFILES_DIR1/$SET/tagfile" "$DEST_DIR/$SET/tagfile" || exit 1
else
# Found tagfiles in both dirs - merge the tagfiles into dest dir.
merge_tagfiles "$TAGFILES_DIR1/$SET/tagfile" "$TAGFILES_DIR2/$SET/tagfile" "$DEST_DIR/$SET/tagfile"
fi
fi fi
done done
echo (( FLAG_MANUAL_INPUT == 1 )) && echo