代替コマンドとして、最初のコマンドと同じパラメーターを使用して2番目のコマンドを実行します。

代替コマンドとして、最初のコマンドと同じパラメーターを使用して2番目のコマンドを実行します。

次のコマンドを実行したいと思います。

tar  --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api

ただし、macOSには次の代替措置が必要です。

gtar --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api

(注:パラメータは同じです。)

gtar最初に呼び出してからtarフォールバックで、1行でパラメータを一度だけ書き込むことができますか?

答え1

まず、gtarを呼び出してから、代替手段としてtarを1行で呼び出して、パラメータを一度だけ書くことはできますか?

この質問に答えるには:これは、パラメータを配列に格納する簡単な実装で行うことができます。 (Bash / ksh / zsh。参照変数に保存されたコマンドをどのように実行できますか?問題とPOSIX互換の回避策について学びます。 )

args=(--sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api)
if ! tar "${args[@]}"; then
    echo "using 'tar' failed, retrying with 'gtar'" >&1
    gtar "${args[@]}"
fi

または、次のように主張する場合は、1行で:

tar "${args[@]}" || gtar "${args[@]}"

これは説明できませんが、なぜ問題がアクセスできないディレクトリに似ていても、失敗して別のtarで再試行します。

別のオプションは、最初のコマンドで「コマンドが見つかりません」エラーが発生した場合にコマンドを再実行することです。$?この場合、シェルは通常127に設定されます。もちろん、これはおそらく何らかの形で存在するので、gtar最初に反転する必要があります。tar

gtar "${args[@]}"
ret=$?
if [ "$ret" = 127 ]; then
    tar "${args[@]}"
    ret=$?
fi

テストでは[ "$? = 127 ]値が削除されるため、$?実際の終了状態を維持するには追加の変数が必要です。

2つのタールがある特別な場合には、コサロナンダの答えあらかじめ確認してみるのも良い解決策だ。

答え2

tarmacOS で Homebrew インストーラを使用して GNU をインストールした場合、gnu-tar端末に次のメッセージが表示されます。

GNU "tar" has been installed as "gtar".
If you need to use it as "tar", you can add a "gnubin" directory
to your PATH from your bashrc like:

    PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"

つまり、上記のインストールメッセージのように最初にtar設定すると、質問の先頭のコマンドが期待どおりに機能することを意味します。PATHgnu-tar

PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
tar  --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api

条件付き更新PATH:

if [ "$(uname)" = Darwin ]; then
    PATH="/usr/local/opt/gnu-tar/libexec/gnubin:$PATH"
fi

tar  --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api

以下を使用してテストすることもできますcommand -v

if command -v gtar >/dev/null 2>&1; then
    tar=gtar
elif command -v tar >/dev/null 2>&1 && tar --version | grep -q -F GNU 2>/dev/null; then
    tar=tar
else
    echo 'No GNU tar available' >&2
    exit 1
fi

"$tar" --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api

gtarコマンドとして存在するかどうかをテストします。その場合、変数はtar文字列に設定されますgtar。存在しない場合はテストし、tar存在する場合は部分文字列を含む項目が返されるかどうかをtarテストし、その文字列を変数に割り当てます。ただし、テストが失敗した場合は診断メッセージで終了します。tar --versionGNUtartar

後でエラーメッセージで終了しない場合は、"$tar"asコマンドを使用してください。

uname明らかに、次の出力をテストすることもできます。

if [ "$(uname)" = Darwin ]; then
    # Assumes GNU tar is gtar on macOS and that it's available
    tar=gtar
else
    # Assumes GNU tar is tar on this system, and that it's available
    tar=tar
fi

"$tar" --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2020-01-01' -cvf api.tar api

関連情報