diff --git a/scripts/copy_output.sh b/scripts/copy_output.sh
index 8966e49e631123523268d310444a3d0ecd316a9d..8f8643ea03f48711b4e17dfc4da4e039de2727d4 100755
--- a/scripts/copy_output.sh
+++ b/scripts/copy_output.sh
@@ -33,33 +33,49 @@ fi
 SITE_CODE="$(scripts/site.sh site_code)"
 PACKAGE_PREFIX="gluon-${SITE_CODE}-${GLUON_RELEASE}"
 
-copy() {
-	[ "${output}" ] || return 0
-	want_device "${output}" || return 0
-
-	if [ "$factory_ext" ]; then
-		rm -f "${GLUON_IMAGEDIR}/factory/gluon-"*"-${output}${factory_ext}"
-		cp "openwrt/bin/targets/${OPENWRT_BINDIR}/openwrt-${OPENWRT_TARGET}${profile}${factory_suffix}${factory_ext}" \
-			"${GLUON_IMAGEDIR}/factory/gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}${factory_ext}"
-
-		for alias in $aliases; do
-			rm -f "${GLUON_IMAGEDIR}/factory/gluon-"*"-${alias}${factory_ext}"
-			ln -s "gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}${factory_ext}" \
-				"${GLUON_IMAGEDIR}/factory/gluon-${SITE_CODE}-${GLUON_RELEASE}-${alias}${factory_ext}"
-		done
-	fi
 
-	if [ "$sysupgrade_ext" ]; then
-		rm -f "${GLUON_IMAGEDIR}/sysupgrade/gluon-"*"-${output}-sysupgrade${sysupgrade_ext}"
-		cp "openwrt/bin/targets/${OPENWRT_BINDIR}/openwrt-${OPENWRT_TARGET}${profile}${sysupgrade_suffix}${sysupgrade_ext}" \
-			"${GLUON_IMAGEDIR}/sysupgrade/gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}-sysupgrade${sysupgrade_ext}"
+do_clean() {
+	local dir="$1"
+	local out_suffix="$2"
+	local ext="$3"
+	local name="$4"
 
-		for alias in $aliases; do
-			rm -f "${GLUON_IMAGEDIR}/sysupgrade/gluon-"*"-${alias}-sysupgrade${sysupgrade_ext}"
-			ln -s "gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}-sysupgrade${sysupgrade_ext}" \
-				"${GLUON_IMAGEDIR}/sysupgrade/gluon-${SITE_CODE}-${GLUON_RELEASE}-${alias}-sysupgrade${sysupgrade_ext}"
-		done
-	fi
+	rm -f "${GLUON_IMAGEDIR}/${dir}/gluon-"*"-${name}${out_suffix}${ext}"
+}
+
+get_file() {
+	local dir="$1"
+	local out_suffix="$2"
+	local ext="$3"
+	local name="$4"
+
+	echo "${GLUON_IMAGEDIR}/${dir}/gluon-${SITE_CODE}-${GLUON_RELEASE}-${name}${out_suffix}${ext}"
+}
+
+do_copy() {
+	local dir="$1"
+	local in_suffix="$2"
+	local out_suffix="$3"
+	local ext="$4"
+	local aliases="$5"
+
+	local file="$(get_file "$dir" "$out_suffix" "$ext" "$output")"
+
+	do_clean "$dir" "$out_suffix" "$ext" "$output"
+	cp "openwrt/bin/targets/${OPENWRT_BINDIR}/openwrt-${OPENWRT_TARGET}${profile}${in_suffix}${ext}" "$file"
+
+	for alias in $aliases; do
+		do_clean "$dir" "$out_suffix" "$ext" "$alias"
+		ln -s "$(basename "$file")" "$(get_file "$dir" "$out_suffix" "$ext" "$alias")"
+	done
+}
+
+copy() {
+	[ "$output" ] || return 0
+	want_device "$output" || return 0
+
+	[ -z "$factory_ext" ] || do_copy 'factory' "$factory_suffix" '' "$factory_ext" "$aliases"
+	[ -z "$sysupgrade_ext" ] || do_copy 'sysupgrade' "$sysupgrade_suffix" '-sysupgrade' "$sysupgrade_ext" "$aliases"
 }