Właściwy sposób
Naprawdę powinieneś używać, gtk-launch
jeśli jest dostępny. Zwykle jest to część pakietu libgtk-3-bin (może to różnić się w zależności od dystrybucji).
gtk-launch
jest używany w następujący sposób:
gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name
Uwaga: gtk-launch
wymaga zainstalowania pliku .desktop (tj. Umieszczonego w /usr/share/applications
lub ~/.local/share/applications
).
Aby obejść ten problem, możemy użyć chwiejnej funkcji Bash, która tymczasowo instaluje żądany plik .desktop przed jego uruchomieniem. „Prawidłowy” sposób instalacji pliku .desktop polega na tym, desktop-file-install
ale zignoruję to.
launch(){
# Usage: launch PATH [URI...]
# NOTE: The bulk of this function is executed in a subshell, i.e. `(..)`
# This isn't strictly necessary, but it keeps everything
# out of the global namespace and lessens the likelihood
# of side effects.
(
# where you want to install the launcher to
appdir=$HOME/.local/share/applications
# the template used to install the launcher
template=launcher-XXXXXX.desktop
# ensure $1 has a .desktop extension, exists, is a normal file, is readable, has nonzero size
# optionally use desktop-file-validate for stricter checking
# desktop-file-validate "$1" 2>/dev/null || {
[[ $1 = *.desktop && -f $1 && -r $1 && -s $1 ]] || {
echo "ERROR: you have not supplied valid .desktop file" >&2
return 1
}
# ensure the temporary launcher is deleted upon exit
trap 'rm "$launcherfile" &>/dev/null' EXIT
# create a temp file to overwrite later
launcherfile=$(mktemp -p "$appdir" "$template")
launchername=${launcherfile##*/}
# overwrite temp file with the launcher file
if cp "$1" "$launcherfile" &>/dev/null; then
gtk-launch "$launchername" "${@:2}"
else
echo "ERROR: failed to copy launcher to applications directory" >&2
return 1
fi
)
}
Możesz użyć go w ten sposób (a także przekazać dodatkowe argumenty lub identyfikatory URI, jeśli chcesz):
launch PATH [URI...]
launch ./path/to/shortcut.desktop
Manualna alternatywa
Jeśli chcesz ręcznie przeanalizować i wykonać plik .desktop , możesz to zrobić za pomocą następującego awk
polecenia:
awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop
Jeśli chcesz traktować awk
polecenie jak skrypt typu „wszystko w jednym”; możemy nawet wyświetlić komunikat o błędzie i wyjść z kodem powrotu 1, jeśli nie zostanie znalezione polecenie Exec :
awk 'BEGIN {command=""} /^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); command=$0; exit} END {if (command!="") {exit system(command)} else {if (FILENAME == "-") {printf "ERROR: Failed to identify Exec line\n" > "/dev/stderr"} else {printf "ERROR: Failed to identify Exec line in \047%s\047\n", FILENAME > "/dev/stderr"} close("/dev/stderr"); exit 1}}'
Wyżej wymienione polecenia będą:
- Znajdź linię zaczynającą się od Exec =
- Usuń Exec =
- Usunąć wszelkie zmienne Exec (np
%f
, %u
, %U
). Możliwe jest zastąpienie ich argumentami pozycyjnymi zgodnie z zamierzeniami specyfikacji, ale spowodowałoby to znaczną złożoność problemu. Zobacz najnowszą specyfikację wpisu na pulpicie .
- Wykonaj polecenie
- Natychmiast wyjdź z odpowiednim kodem wyjścia (aby nie wykonywać wielu wierszy Exec )
Uwaga: ten skrypt AWK rozwiązuje kilka przypadków skrajnych, które mogą, ale nie muszą być poprawnie rozwiązane przez niektóre inne odpowiedzi. W szczególności to polecenie usuwa wiele zmiennych Exec (uważając, aby w przeciwnym razie nie usunąć symbolu%), wykona tylko jedno polecenie wiersza Exec i zachowa się zgodnie z oczekiwaniami, nawet jeśli polecenie wiersza Exec zawiera jeden lub więcej znaków równości (np script.py --profile=name
.).
Tylko kilka innych zastrzeżeń ... Zgodnie ze specyfikacją TryExec to:
Ścieżka do pliku wykonywalnego na dysku używanego do ustalenia, czy program jest faktycznie zainstalowany. Jeśli ścieżka nie jest ścieżką bezwzględną, plik jest sprawdzany w zmiennej środowiskowej $ PATH. Jeśli plik nie istnieje lub nie jest wykonywalny, wpis może zostać zignorowany (na przykład nie może być używany w menu).
Mając to na uwadze, nie ma sensu wykonywać jego wartości.
Inne obawy dotyczą ścieżki i terminala . Ścieżka składa się z katalogu roboczego do uruchomienia programu. Terminal to wartość logiczna, która wskazuje, czy program jest uruchamiany w oknie terminala. Można to wszystko rozwiązać, ale nie ma sensu wymyślać koła, ponieważ istnieją już implementacje specyfikacji. Jeśli chcesz wdrożyć ścieżkę , pamiętaj, że system()
spawnuje podproces, więc nie możesz zmienić katalogu roboczego, wykonując coś takiego system("cd \047" working_directory "\047"); system(command)
. Można jednak przypuszczalnie zrobić coś takiego system("cd \047" working_directory "\047 && " command)
. Uwaga \ 047 to pojedyncze cudzysłowy (więc polecenie nie pęka na ścieżkach ze spacjami).
Python Alternative
Jestem kradzież stronę z Carlo tutaj , który zasugerował stworzenie skryptu Pythona aby skorzystać z gi modułu. Oto minimalny sposób wykonania tego samego kodu z powłoki bez konieczności tworzenia pliku i martwienia się o operacje we / wy.
launch(){
# Usage: launch PATH [URI...]
python - "$@" <<EOF
import sys
from gi.repository import Gio
Gio.DesktopAppInfo.new_from_filename(sys.argv[1]).launch_uris(sys.argv[2:])
EOF
}
Następnie uruchom funkcję uruchamiania w następujący sposób:
launch ./path/to/shortcut.desktop
Uwaga: użycie identyfikatorów URI jest opcjonalne. Ponadto nie jest przeprowadzane sprawdzanie błędów, więc upewnij się, że program uruchamiający istnieje i jest czytelny (przed użyciem), jeśli chcesz, aby skrypt był trwały.
exec
niepowodzenia jest to, że exec zastępuje aktualnie uruchomiony proces określonym przez Ciebie procesem, więc próbujesz zastąpić powłokę uruchomionym pulpitem jako skompilowanym plikiem binarnym. Powodem, dla którego nie możesz tego zrobić,sudo exec
jest to, że jest to wbudowana powłoka, a nie polecenie binarne.