パラメータの内容を実行せずにコマンドにパラメータを渡すにはどうすればよいですか?

パラメータの内容を実行せずにコマンドにパラメータを渡すにはどうすればよいですか?

良い時間。

少し問題があります。 bashスクリプトにこの機能があります

function denyCheck(){
    file=$(readlink -f $(which $(printf "%s\n" "$1")))
    if [[ -x $file ]];then
           return false
    else
           return true
    fi
}
denyCheck "firefox"

この関数は、彼女にコマンドが何であるかを文字列を渡します。これはコマンドのある元のパス(/usr/lib/firefox/firefox.shなど)をチェックし、ファイルが実行可能な場合はtrueを返し、そうでない場合はfalseを返します。

しかし、問題は...パラメータ(たとえば、「firefox」)がコマンドを実行してブラウザFirefoxを開くことです。

パラメータが実行されないようにするにはどうすればよいですか?

とても感謝しています。

答え1

それ以上でなければなりません:

cmd_canonical_path() {
  local cmd_path
  cmd_path=$(command -v -- "$1") &&
    cmd_path=$(readlink -e -- "$cmd_path") &&
    [ -x "$cmd_path" ] &&
    REPLY=$cmd_path
} 2> /dev/null

次に、たとえば、次のようにします。

if cmd_canonical_path firefox; then
  printf '%s\n' "firefox found in $REPLY executable"
else
  printf >&2 '%s\n' "no executable file found for firefox"
fi

シェルでは、すべてのコマンドに成功(0)または失敗(さまざまな種類の失敗を区別するのに役立つ値を持つ他の数字)を示す終了ステータスがあります。

たとえば、コマンドを実行するプロセスにファイル(またはディレクトリ)に対する実行権限がある場合、コマンド[-x引数として渡されたときにtrueを返します。/path/to/some/file]/path/to/some/file

関数には、戻り前の最後のコマンド実行の終了状態(またはreturn呼び出し時に渡された番号)である終了状態もあります。

ifコマンドの成功または失敗のステータスは、//ステートメントまたは対応するブール演算子sumなどのシェル構成でuntil確認されます。while||&&注文する必要に応じてシェルのブール値です。

cmd1 && cmd2 && cmd3成功/trueを返します。すべてはい、cmd1成功です。失敗しても実行されません。cmd2cmd3cmd2cmd1cmd3

cmd_canonical_pathしたがって、上記の場合は成功しますcommand -v -- "$1"(コマンドを見つけてそのパスを印刷するための標準組み込み1コマンド、whichいくつかの同様のコマンドですが、cshユーザーのみ)。そしてその後readlink -e(正規化されたパスのように動作しますが、最善の努力を尽くすreadlink -fことができない場合は失敗を返します)readlink -fそしてその後、現在のプロセスにはファイルに対する実行権限があります。そして次に、パスはREPLY4番目の変数に正常に割り当てられます(通常の割り当ては常に成功します)。

cmd && cmd && cmdそれ以外の場合、関数は失敗(失敗したチェーンの最初のコマンドの終了ステータス)を返します。

$REPLYまた、コマンドへの正規パスを決定できない場合、またはコマンドを実行できない場合は、コマンドが変更されずに保存されることにも注意してください。

あなたのアプローチにはいくつかの他の問題があります。

  • これは$(printf '%s\n' "$1")あまり意味がありません。 sh / bashでは$1(少なくともデフォルト)と同じであり、$IFS引用されていないので、同じことが間違っています。最初の位置引数の内容をコマンドに渡したい場合は、構文はですcmd "$1"
  • オプションではなく引数として処理されるようにコマンドに渡された任意のデータが必要な場合は、オプションの終わりを示す引数の後にそれを--渡す必要があります。which -- "$1"readlink -f -- "$(...)"
  • returntrue/代わりに(オプションの)数値を引数(関数の終了コード)として受け入れますfalse(ファイルが実行可能であれば関数がtrueを返すと言ったので、これを逆にしたようです)。数値が渡されない場合、関数の終了状態は、関数内で実行された最後のコマンドの終了状態になります。だからif cmd; then return 0; else return 1; fiそれを書くのが最善ですcmd; return。ここでは(あなたの場合)関数の最後のコマンドなので、return必要ありません。cmd[[ -x $file ]]
  • まず成功かどうかを確認せずwhich(を忘れて--引用したので不正確に$(...))の出力を盲目的に渡しました。readlink

最後にを代わりに使用すると、zshbashのようにできます。

firefox_path==firefox
firefox_canonical_path=$firefox_path:P

firefoxコマンドのパスを取得します。=firefoxコマンドのパスに展開してfirefoxコマンドが見つからない場合は、エラーでシェルを停止します。エラーをブロックできます。always詰まった必要に応じて。この:P修飾子は、realpath()GNUの操作と同様に適用される引数に対して同じことを行いますreadlink -fzsh=cmd演算子は実行パスにのみ拡張されるため、実行権限を確認する必要はありません。


¹シェルに組み込まれているコンポーネントなので、シェルのドキュメントにそのドキュメントを見つけることができます。については例をbash参照してくださいinfo bash command

²command -v cmd出力cmdcmd関数またはシェル組み込み関数であるため、問題になる可能性があります。

³標準絶対パスはで始まり/、シンボリックリンクコンポーネントがなく(すべてターゲットとして識別されます)、/コンポーネントがなく、2つ以上のsシーケンスが.ありません。../

4は、 $REPLY関数またはシェル組み込み関数の戻り値のデフォルト変数としてよく使用されます(単なる慣例にすぎません)。または、関数で次のことを実行できます。出力その結果、呼び出し側はを実行しますfirefox_path=$(cmd_canonical_path firefox)

答え2

これ:

function denyCheck(){

func()標準関数宣言とkshが混在していますfunction func。 Bashはこの組み合わせをサポートし、他のシェルはそうではないかもしれませんが、その理由はありません。ただ書くdenyCheck()

ここでは、

file=$(readlink -f $(which $(printf "%s\n" "$1")))

これは$(printf ...)不要で引用されていないため、実際には非生産的です。このコマンド置換の結果は次の影響を受けます。噴射、引用された内容は"$1"そうではないので、代わりに使用できます。

whichいくつかの問題があると考えられる標準のPOSIXの代替案については、以下をcommand -v参照してください。「which」を使わないのはなぜですか?それでは何を使うべきですか?

2つの主な違いは、組み込みcommandシェルであり、例えばエイリアスについて知っているのですが(対話型シェルで実行している場合)、そうでwhichないことです(cshを除いて使用しない)。これは良いことかもしれません。たとえば、使用可能なパスではないをcommand -v ls返すことができます。alias ls='ls -vF --color=auto'

--いずれにせよ、単語の分離の問題を回避し、タグオプションの終わりを追加するには、コマンドの置き換えを引用する必要があります。これは、スペースを含むまたはで終わるまれなパスを防ぐためです-

file=$(readlink -f -- "$(command -v -- "$1")")  # or
file=$(readlink -f -- "$(which -- "$1")") 

次に、

return false

ただのバグです。returnコマンドに数字が必要です。ただし、falseエラーの戻り状態を取得するために名前付きコマンドを実行できます。したがって、または return 1justのいずれかを使用してくださいfalse。 (テスト結果を反転させるので、! [[ -x "$file" ]]if全体の代わりにjustを使用することもできます。

だから:

denycheck() {
    file=$(readlink -f -- "$(command -v -- "$1")")
    if [[ -x "$file" ]]; then
        return 1  # command found and executable, falsy result
    else
        return 0  # not executable, truthy result
    fi
}

関連情報