Ubuntu – Running a long command, split into multiple lines, in a .desktop file

command linedesktopgnomescripts

Say we have this file, start-term-tabs.sh:

gnome-terminal \
  --tab --title="Term 1" \
    --working-directory=/tmp \
    -e "bash -i" \
  --tab-with-profile=Default --title="Term 2" \
    --working-directory=/home \
    -e "bash -i" \
  --tab-with-profile=Default --title="Term 3" \
    --working-directory=/etc \
    -e "bash -i"

Because this is a long command, and for readibility reasons, I like to split it in multiple lines, by escaping the line feed on each line. By doing chmod +x start-term-tabs.sh, I can double-click the start-term-tabs.sh on the desktop and it will start, but it will show the super-annoying 'Do you want to run "start-term-tabs.desktop", or display its contents?':

doyouwant

… on which I have to click "Run" each time.

Now, I could make a test.desktop file like this:

[Desktop Entry]
Name=start-term-tabs test
Terminal=false
Type=Application
Icon=/usr/share/app-install/icons/terminal-tango.svg
Exec=/home/USER/Desktop/start-term-tabs.sh

… and after doing chmod +x test.desktop, everything runs; but then I have to manage two files, and I'd instead like to manage only one file.

So, I tried tucking in the entire above gnome-terminal command line in there, and when it is as a single line in the Exec field:

Exec=gnome-terminal   --tab --title="Term 1"     --working-directory=/tmp     -e "bash -i"   --tab-with-profile=Default --title="Term 2"     --working-directory=/home     -e "bash -i"   --tab-with-profile=Default --title="Term 3"     --working-directory=/etc     -e "bash -i"

… it also does work fine, but it is quite difficult for me to manage it when it is on only one line.

But when I try to split it inside the .desktop file, that is:

[Desktop Entry]
Name=start-term-tabs test
Terminal=false
Type=Application
Icon=/usr/share/app-install/icons/terminal-tango.svg
Exec=gnome-terminal \
  --tab --title="Term 1" \
    --working-directory=/tmp \
    -e "bash -i" \
  --tab-with-profile=Default --title="Term 2" \
    --working-directory=/home \
    -e "bash -i" \
  --tab-with-profile=Default --title="Term 3" \
    --working-directory=/etc \
    -e "bash -i"

… then as soon as I save this, the icon is not shown on the .desktop file any more, that is it starts looking like this:

deskicon

… and so it is not treated as a valid .desktop file, so when it is double-clicked, again I get the "Do you want to run…" prompt, and even if I say Run, no gnome-terminal is started, so something ends up horribly here.

So, how could I split a long command for the Exec field in a .desktop file in multiple lines, – possibly using some sort of escaping – and still have it run properly?

I've seen https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables, and I've tried using \\ everywhere instead of just \, but that doesn't help – and I otherwise cannot tell what I should do to get this working…

Best Answer

I have a super hack that involves setting a bash variable to the contents of the script you want to run, then echoing it into the .desktop file. Read past the details of my specific script, but pay attention to quotes and semicolons. The hack encodes the program as a shell variable, then uses echo to collapse all the newlines into a single line and append it to a Gnome desktop launcher file.

For context, I have a file called Win10.desktop that connects to a headless VirtualBox instance; it reconfigures the network adapter based on whether the laptop is docked or free-standing. I am on RHEL 7.6 / Gnome 3.

(I could have written the script w/o spaces, but that's hard to read. I keep the original in a README_REINSTALL file somewhere else, in case I ever trash my system and have to recreate it from scratch.)

PROG='
PATH=/usr/lib/virtualbox:/usr/bin:bin ;
VM="{045c7bf0-555e-4675-b95c-f8814d689077}" ;
WNIC="wlo1" ;
DNIC="enp58s0u1u2" ;
VMNAME="Win10" ;
ACTION=$(zenity --list --text "Choose action for $VMNAME" --radiolist --column "" --column "" 
        --hide-header 
            TRUE  "Full GUI Start/Resume" 
            FALSE "Suspend") ;
case $ACTION in 
        Full*) 
            echo "Starting" ;
            grep -q $DNIC /proc/net/dev && vboxmanage modifyvm $VM --bridgeadapter1 $DNIC || 
                vboxmanage modifyvm $VM --bridgeadapter1 $WNIC ;
            exec vboxmanage startvm $VM --type gui 
        ;;
        Suspend*) 
            echo "Suspending" ;
            vboxmanage modifyvm $VM --bridgeadapter1 $WNIC ;
            exec vboxmanage controlvm $VM savestate
        ;; 
esac'

echo Exec=/usr/bin/bash -c \'$PROG\' >> Win10.desktop
Related Question