看板 Linux 關於我們 聯絡資訊
分享一下 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://www.ptt.cc/bbs/Linux/M.1699182818.A.AB4.html ※ 編輯: sppmg (101.12.88.235 臺灣), 11/05/2023 19:25:17
microloft: 都寫進 .sh 了,其實可以不用 bash -c 多包一層 11/06 01:09
sppmg: 因為我一開始沒辦法直接執行sh啊!XD 11/06 06:28
sppmg: 如果哪天遇到上層不會自動用sh執行腳本的話可以這樣指定。 11/06 06:30
brli7848: 到那時候,直接指定#!/bin/bash就好了吧? 11/06 10:20