Skip to content

Instantly share code, notes, and snippets.

@raffraffraff
Last active January 11, 2023 11:56
Show Gist options
  • Save raffraffraff/dc95fea669d5c58e289d5a988698e38c to your computer and use it in GitHub Desktop.
Save raffraffraff/dc95fea669d5c58e289d5a988698e38c to your computer and use it in GitHub Desktop.
AppImage2Deb
#!/bin/bash
# About: This script turns AppImages into regular old .deb files which install the app to /opt/${APP_NAME} and handle icons and .desktop file
fatal() {
echo $@
exit 1
}
[[ -x $(which fakeroot) ]] || fatal "Missing fakeroot. Run 'sudo apt-get install fakeroot'"
APP_IMAGE=$(readlink -f $1)
APP_DIR=$(dirname $APP_IMAGE)
if [ -f ${APP_IMAGE} ]; then
if [ ! -x ${1} ]; then
chmod +x "${APP_IMAGE}"
fi
OFFSET=$(${APP_IMAGE} --appimage-offset)
if [ $? -ne 0 ]; then
MOUNT_OPTIONS="-o loop"
else
if [ ${OFFSET} -gt 0 ]; then
MOUNT_OPTIONS="-o offset=${OFFSET}"
else
fatal "AppImage offset is ${OFFSET} which just seems wrong"
fi
fi
else
fatal "Usage: $0 <App.AppImage>"
fi
MOUNT_DIR=$(mktemp -d)
sudo mount ${MOUNT_OPTIONS} "$APP_IMAGE" "${MOUNT_DIR}" || fatal "Failed command: 'mount ${MOUNT_OPTIONS} ${APP_IMAGE} ${MOUNT_DIR}'"
DEB_SRC=$(mktemp -d)
mkdir -p "${DEB_SRC}/opt/"
mkdir -p "${DEB_SRC}/usr/share/applications"
ICON_FILE=$(find "${MOUNT_DIR}" -maxdepth 1 -type l -name '*.png' -o -name '*.svc')
if [ -f "${ICON_FILE}" ]; then
ICON_NAME=$(basename ${ICON_FILE%.*})
else
ICON_NAME=${APP_NAME}
fi
DESKTOP_FILE=$(find "${MOUNT_DIR}" -maxdepth 1 -type f -name '*.desktop')
if [ -f "${DESKTOP_FILE}" ]; then
APP_NAME=$(awk -F= '$1 == "Name" { print $2 }' "${DESKTOP_FILE}")
APP_DESC=$(awk -F= '$1 == "Comment" { print $2 }' "${DESKTOP_FILE}")
cat ${DESKTOP_FILE} \
| sed "s#Exec=AppRun.*#Exec=/opt/${APP_NAME}/AppRun#" \
| sed "s#Icon=.*#Icon=${ICON_NAME}#" \
> "${DEB_SRC}/usr/share/applications/${APP_NAME}.desktop"
else
APP_NAME=$(basename ${APP_IMAGE%.*})
APPDESC="${APP_NAME} for Desktop"
cat <<-EOF > "${DEB_SRC}/usr/share/applications/${APP_NAME}.desktop"
[Desktop Entry]
Name=${APP_NAME}
Exec=/opt/${APP_NAME}/AppRun --no-sandbox %U
Comment=${APP_DESC}
Terminal=false
Type=Application
Icon=${ICON_NAME}
EOF
fi
mkdir -p ${DEB_SRC}/DEBIAN
cat <<EOF > ${DEB_SRC}/DEBIAN/control
Package: ${APP_NAME}
Version: $(date +%Y%m%d%H)
Architecture: all
Maintainer: AppImage2Deb
Installed-Size: $(du -s "${MOUNT_DIR}" | awk '{print $1}')
Section: Miscellaneous
Priority: optional
Description: ${APP_DESC}
EOF
cat <<EOF > ${DEB_SRC}/DEBIAN/postinst
#!/bin/sh
update-desktop-database
EOF
cat <<EOF > ${DEB_SRC}/DEBIAN/postrm
#!/bin/sh
update-desktop-database
EOF
chmod 775 ${DEB_SRC}/DEBIAN/post*
# Copy files to package source directory
cp -a "${MOUNT_DIR}" "${DEB_SRC}/opt/${APP_NAME}"
if [ -d "${MOUNT_DIR}/usr/share/icons" ]; then
cp -a "${MOUNT_DIR}/usr/share/icons" "${DEB_SRC}/usr/share/"
fi
sudo umount "${MOUNT_DIR}" && rmdir "${MOUNT_DIR}"
# Generate package md5sums
find "${DEB_SRC}" -type f -not -path "${DEB_SRC}/DEBIAN/*" -exec md5sum {} \; \
| sed "s%${DEB_SRC}/%%" \
> ${DEB_SRC}/DEBIAN/md5sums
# Build the package
fakeroot dpkg-deb -b "${DEB_SRC}" "${APP_DIR}/${APP_NAME}.deb"
@faveoled
Copy link

Fails if AppImage app name contains spaces:

dpkg-deb: error: parsing file '/tmp/tmp.StcPOxKWl2/DEBIAN/control' near line 1:
 invalid package name in 'Package' field: character ' ' not allowed (only letters, digits and characters '-+._')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment