bashスクリプトは、パラメーターを指定してコマンドを実行し、コマンド全体をファイルに書き込みます。

bashスクリプトは、パラメーターを指定してコマンドを実行し、コマンド全体をファイルに書き込みます。

コマンドを実行してファイルに追加する一般的なスクリプトが必要です。

私の試みは次のとおりです(という実行可能ファイルに保存されています./action)。

#!/bin/bash
#runs command and logs result to "./actions"

if "$@"; then
    echo "#"$(date)"(success)" >> ./actions
else
    read -p "Exit code is fail. Still record to ./actions (y)? " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]
    then
        exit 1
    fi
    echo "#"$(date)"(failed)" >> ./actions
fi
echo "$@" >> ./actions

私が経験している問題は次のとおりです。

./action touch "new file"

正しく実行されますが、bashは保存のみです。

touch new file

とは明らかにtouch new file異なりますtouch "new file"

引用符付き引数を含むコマンドを正しく記録するようにこのスクリプトを変更するにはどうすればよいですか?

答え1

興味深い質問です。私はあなたが望むことが完全に可能であるとは思わないが、%qBashの実装で使用できる型指定子を使うとかなり近づくことができます。printf

%q は、printf がその引数をシェル入力として再利用できる形式で出力するようにします。

スクリプトの最後の数行は次のとおりです。

printf "%q\n" "$@" | tr '\n' ' ' >> actions
printf "\n" >> actions

これはコマンドを入力したまま記録するのではなく、シェルで使用するのに適した形式でコマンドを記録するため、記録されたコマンドを入力すると、もともと期待した結果が得られます。たとえば、次のようにします。

./action touch "new file"

あなたは以下を得ます:

#Wed Sep 4 14:10:57 CEST 2019(success)
touch new\ file

または以下を実行した後:

./action echo 'one
two
three
'

あなたは以下を得ます:

#Wed Sep 4 14:11:44 CEST 2019(success)
echo $'one\ntwo\nthree\n'

ちなみに、shellcheckスクリプトに2つのバグが報告されました。

$ ~/.cabal/bin/shellcheck action

In action line 5:
    echo "#"$(date)"(success)" >> ./actions
            ^-- SC2027: The surrounding quotes actually unquote this. Remove or escape them.
            ^-- SC2046: Quote this to prevent word splitting.


In action line 13:
    echo "#"$(date)"(failed)" >> ./actions
            ^-- SC2027: The surrounding quotes actually unquote this. Remove or escape them.
            ^-- SC2046: Quote this to prevent word splitting.

関連情報