作者sppmg (sppmg)
看板Linux
标题[心得] bash -c 与 Dolphin Service Menus
时间Sun Nov 5 19:13:34 2023
分享一下 bash -c 的参数传递方式!
----- 前言 -----
原本想利用 Dolphin Service Menu ,可以在档案管理器中对选择档案执行处理
(例如 jpg2avif )。
结果 .desktop 里面无法直接指定脚本,显示「execvp: 可执行档格式错误」
(在研究许久後才发现
原来 .sh 档头我漏了「!」,打成「#/bin/bash」 XD
.desktop 这样设定是正确的,卡很久是因为不知道 Dolphin 到底会怎样处理脚本)
Exec=img2avif.sh %F
不过若是改由以下方式就能正常执行
Exec=bash -c 'img2avif.sh "%f"'
上面会有几个问题:
1. %f 只会传单一档案
2. %F 可以传多个档案的路径,但一旦遇到路径包含空格就会被拆开。
3. 如果 %F 放在引号外面, sh 无法接收到任何参数。
再仔细研究一下 bash -c 的语法,才发现关於参数传递我还不够了解!
----- bash -c 参数传递 -----
man bash:
-----------
-c If the -c option is present, then commands are read from the
first
non-option argument command_string. If there are arguments after the
command_string, the first argument is assigned to $0 and any remaining
arguments
are assigned to the positional parameters. The assignment to $0 sets the
name
of the shell, which is used in warning and error messages.
-----------
简单说,
"-c command_string" 後面的参数会传入 command_string,并且是从 $0 开始。
因此如果要传给 command_string 内的 .sh 必须再加上
"$@"
结论就是; .desktop 中设定
(如果要透过 bash -c)应该如下:
Exec=bash -c 'img2avif.sh "$@" ' 'dummy-param' %F
下面是一些测试,不太懂的看看应该能明白。
-----------------------
## 准备同一份指令给 -c 与 .sh
$ cmd='echo argc=$#, \$0=\"$0\", \$1=\"$1\", \$2=\"$2\"'
$ echo -e '#!/bin/bash \n'"$cmd" > a.sh
$ chmod u+x a.sh
## 用 bash 直接执行 .sh
$ bash a.sh dd 11 "2 2"
argc=3, $0="a.sh", $1="dd", $2="11"
## 透过 -c 执行 command_string
$ bash -c "$cmd" dd 11 "2 2"
argc=2, $0="dd", $1="11", $2="2 2"
## 透过 -c 执行 .sh (此为正确方式)
$ bash -c '/fullPathTo/a.sh "$@" ' dd 11 "2 2"
argc=2, $0="/fullPathTo/a.sh", $1="11", $2="2 2"
$ bash -c '/fullPathTo/a.sh "$*" ' dd 11 "2 2"
argc=1, $0="/fullPathTo/a.sh", $1="11 2 2", $2=""
$ bash -c '/fullPathTo/a.sh $* ' dd 11 "2 2"
argc=3, $0="/fullPathTo/a.sh", $1="11", $2="2"
-----------------------
note:
* "$@" is equivalent to "$1" "$2" ...
* Dolphin Service Menus
https://develop.kde.org/docs/apps/dolphin/service-menus/
* Desktop Entry Specification
https://specifications.freedesktop.org/desktop-entry-spec/latest
* 单纯转档的话可以直接用 magick 就好(搭配 gnu parallel 更完美)。
这里是假设需要做复杂处理。
* 也可以将指令压缩为单行放进 command_string 执行,这比较适合不想分两个档
或想便於发布的情况。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 101.12.88.235 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Linux/M.1699182818.A.AB4.html
※ 编辑: sppmg (101.12.88.235 台湾), 11/05/2023 19:25:17
1F:推 microloft: 都写进 .sh 了,其实可以不用 bash -c 多包一层 11/06 01:09
2F:→ sppmg: 因为我一开始没办法直接执行sh啊!XD 11/06 06:28
3F:→ sppmg: 如果哪天遇到上层不会自动用sh执行脚本的话可以这样指定。 11/06 06:30
4F:推 brli7848: 到那时候,直接指定#!/bin/bash就好了吧? 11/06 10:20