Đúng cách
Bạn nên thực sự sử dụng gtk-launch
nếu nó có sẵn. Nó thường là một phần của gói libgtk-3-bin (điều này có thể thay đổi theo bản phân phối).
gtk-launch
được sử dụng như sau:
gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name
Xin lưu ý rằng gtk-launch
yêu cầu tệp .desktop phải được cài đặt (nghĩa là nằm trong /usr/share/applications
hoặc ~/.local/share/applications
).
Vì vậy, để giải quyết vấn đề này, chúng ta có thể sử dụng một hàm Bashish nhỏ, tạm thời cài đặt tệp .desktop mong muốn trước khi khởi chạy nó. Cách "chính xác" để cài đặt tệp .desktop là thông qua desktop-file-install
nhưng tôi sẽ bỏ qua điều đó.
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
)
}
Bạn có thể sử dụng nó như vậy (và cũng chuyển qua các đối số hoặc URI bổ sung nếu bạn muốn):
launch PATH [URI...]
launch ./path/to/shortcut.desktop
Hướng dẫn thay thế
Nếu bạn muốn phân tích thủ công và thực thi tệp .desktop , bạn có thể làm như vậy với awk
lệnh sau :
awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop
Nếu bạn muốn coi awk
lệnh như một kịch bản tất cả trong một; chúng ta thậm chí có thể hiển thị thông báo lỗi và thoát với mã trả về là 1 trong trường hợp không tìm thấy lệnh 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}}'
Các lệnh đã nói ở trên sẽ:
- Tìm dòng bắt đầu bằng Exec =
- Xóa Exec =
- Hủy bỏ bất kỳ biến Exec (ví dụ
%f
, %u
, %U
). Có thể thay thế chúng bằng các đối số vị trí như thông số kỹ thuật dự định, nhưng làm như vậy sẽ làm tăng thêm độ phức tạp đáng kể cho vấn đề. Xem thông số kỹ thuật mới nhất của Desktop Desktop .
- Thực hiện lệnh
- Thoát ngay lập tức với mã thoát thích hợp (để không thực thi nhiều dòng Exec )
Lưu ý, tập lệnh AWK này giải quyết một vài trường hợp cạnh có thể được giải quyết đúng hoặc không bằng một số câu trả lời khác. Cụ thể, lệnh này sẽ loại bỏ nhiều biến Exec (chú ý không loại bỏ ký hiệu%), sẽ chỉ thực hiện một lệnh dòng Exec duy nhất và sẽ hoạt động như mong đợi ngay cả khi lệnh dòng Exec chứa một hoặc nhiều dấu bằng (ví dụ script.py --profile=name
).
Chỉ cần một vài cảnh báo khác ... Theo thông số kỹ thuật, TryExec là:
Đường dẫn đến một tệp thực thi trên đĩa được sử dụng để xác định xem chương trình có thực sự được cài đặt hay không. Nếu đường dẫn không phải là đường dẫn tuyệt đối, tệp sẽ được tra cứu trong biến môi trường $ PATH. Nếu tập tin không có mặt hoặc nếu nó không được thực thi, mục nhập có thể bị bỏ qua (ví dụ không được sử dụng trong các menu).
Với ý nghĩ đó, sẽ không có ý nghĩa gì khi thực hiện giá trị của nó.
Một số mối quan tâm khác là Path và Terminal . Đường dẫn bao gồm thư mục làm việc để chạy chương trình. Terminal là một boolean cho biết chương trình có chạy trong cửa sổ terminal không. Tất cả đều có thể được giải quyết, nhưng không có ý nghĩa gì trong việc phát minh lại bánh xe vì đã có triển khai thông số kỹ thuật. Nếu bạn muốn thực hiện Đường dẫn , hãy nhớ rằng system()
sinh ra một quy trình con, vì vậy bạn không thể thay đổi thư mục làm việc bằng cách thực hiện một cái gì đó như system("cd \047" working_directory "\047"); system(command)
. Tuy nhiên, bạn có thể làm điều gì đó như thế system("cd \047" working_directory "\047 && " command)
. Lưu ý \ 047 là các dấu ngoặc đơn (vì vậy lệnh không ngắt trên các đường dẫn có dấu cách).
Thay thế Python
Tôi đang đánh cắp một trang từ Carlo ở đây , người đã đề xuất tạo một tập lệnh Python để sử dụng mô đun gi . Đây là một cách tối thiểu để thực thi cùng một mã từ trình bao mà không phải tạo tệp và lo lắng về I / O.
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
}
Sau đó thực hiện chức năng launcher như sau:
launch ./path/to/shortcut.desktop
Lưu ý việc sử dụng URI là tùy chọn. Ngoài ra, không có kiểm tra lỗi nào được thực hiện nên bạn sẽ muốn đảm bảo trình khởi chạy tồn tại và có thể đọc được (trước khi sử dụng nó) nếu bạn muốn tập lệnh của mình bền.
exec
thất bại của bạn là do exec thay thế quy trình hiện đang chạy của bạn bằng quy trình bạn chỉ định, vì vậy những gì bạn đã làm là cố gắng thay thế trình bao của bạn bằng cách chạy máy tính để bàn dưới dạng nhị phân được biên dịch. Lý do bạn không thểsudo exec
là vì nó được tích hợp sẵn chứ không phải lệnh nhị phân.