
良い時間。
少し問題があります。 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
成功です。失敗しても実行されません。cmd2
cmd3
cmd2
cmd1
cmd3
cmd_canonical_path
したがって、上記の場合は成功しますcommand -v -- "$1"
(コマンドを見つけてそのパスを印刷するための標準組み込み1コマンド、which
いくつかの同様のコマンドですが、cshユーザーのみ)。そしてその後readlink -e
(正規化されたパスのように動作しますが、最善の努力を尽くすreadlink -f
ことができない場合は失敗を返します)readlink -f
そしてその後、現在のプロセスにはファイルに対する実行権限があります。そして次に、パスはREPLY
4番目の変数に正常に割り当てられます(通常の割り当ては常に成功します)。
cmd && cmd && cmd
それ以外の場合、関数は失敗(失敗したチェーンの最初のコマンドの終了ステータス)を返します。
$REPLY
また、コマンドへの正規パスを決定できない場合、またはコマンドを実行できない場合は、コマンドが変更されずに保存されることにも注意してください。
あなたのアプローチにはいくつかの他の問題があります。
- これは
$(printf '%s\n' "$1")
あまり意味がありません。 sh / bashでは$1
(少なくともデフォルト)と同じであり、$IFS
引用されていないので、同じことが間違っています。最初の位置引数の内容をコマンドに渡したい場合は、構文はですcmd "$1"
。 - オプションではなく引数として処理されるようにコマンドに渡された任意のデータが必要な場合は、オプションの終わりを示す引数の後にそれを
--
渡す必要があります。which -- "$1"
readlink -f -- "$(...)"
return
true
/代わりに(オプションの)数値を引数(関数の終了コード)として受け入れますfalse
(ファイルが実行可能であれば関数がtrueを返すと言ったので、これを逆にしたようです)。数値が渡されない場合、関数の終了状態は、関数内で実行された最後のコマンドの終了状態になります。だからif cmd; then return 0; else return 1; fi
それを書くのが最善ですcmd; return
。ここでは(あなたの場合)関数の最後のコマンドなので、return
必要ありません。cmd
[[ -x $file ]]
- まず成功かどうかを確認せず
which
(を忘れて--
引用したので不正確に$(...)
)の出力を盲目的に渡しました。readlink
最後にを代わりに使用すると、zsh
次bash
のようにできます。
firefox_path==firefox
firefox_canonical_path=$firefox_path:P
firefox
コマンドのパスを取得します。=firefox
コマンドのパスに展開してfirefox
コマンドが見つからない場合は、エラーでシェルを停止します。エラーをブロックできます。always
詰まった必要に応じて。この:P
修飾子は、realpath()
GNUの操作と同様に適用される引数に対して同じことを行いますreadlink -f
。zsh
の=cmd
演算子は実行パスにのみ拡張されるため、実行権限を確認する必要はありません。
¹シェルに組み込まれているコンポーネントなので、シェルのドキュメントにそのドキュメントを見つけることができます。については例をbash
参照してくださいinfo bash command
。
²command -v cmd
出力cmd
はcmd
関数またはシェル組み込み関数であるため、問題になる可能性があります。
³標準絶対パスはで始まり/
、シンボリックリンクコンポーネントがなく(すべてターゲットとして識別されます)、/コンポーネントがなく、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 1
justのいずれかを使用してください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
}