内部にバッシュリファレンスマニュアルそれは次のように言います:
lithist
有効にしてcmdhist
このオプションを有効にすると、複数行コマンドは、可能であればセミコロン区切り文字を使用するのではなく、埋め込み行を使用して履歴に保存されます。
だから私の質問は次のようになりますどこで/いつ/どのように可能ですか??
私のデバイスで機能を有効にしてテストしてみました。GNU bash, バージョン 4.4.12(1) - リリースこの方法:
shopts -s cmdhist
shopts -s lithist
echo -n "this is a test for a ";\
echo "multiline command"
それから私は
history | tail
次のような出力が予想されます。
101 shopts -s cmdlist
102 shopts -s lithist
103 echo -n "this is a test for a ";\
echo "multiline command"
104 history
しかし、これを得る:
101 shopts -s cmdlist
102 shopts -s lithist
103 echo -n "this is a test for a "; echo "multiline command"
104 history
明らかに、複数行コマンド(bash履歴番号103)はまだ保存されていません。「セミコロン区切り文字を使用する代わりに挿入行を分割する」。ここではなぜlithist
不可能ですか?私は何が間違っていましたか?
答え1
Aは歴史からaを得る正しい方法では\<new line>
ありません。<new line>
メモリ
書き込み行はディスクではなくシェルメモリに保持されるため、書き込み行のみを処理します。
これまでに行ったように、いくつかのコマンドを入力してみましょう。
$ echo -n "this is a test for a ";\
> echo "two line command"
行が作成されたばかりのメモリに何が保存されましたか?
$ history 2
514 echo -n "this is a test for a ";echo "two line command"
515 history 2
ご覧のとおり、「行の連続」(バックスラッシュの後に改行)が削除されました。
(man bashから)次のようにする必要があります。
\ペアが発生し、バックスラッシュ自体が引用符で囲まれていない場合、\は行連続で処理されます(つまり、入力ストリームから削除され、事実上無視されます)。
引用すると、改行文字が表示されることがあります。
$ echo " A test of
> a new line"
A test of
a new line
そしてこの時点で、歴史は以下を反映します。
$ history 2
518 echo "A test of
a new line"
519 history 2
実際の複数行コマンド:
複数行コマンドの可能な例は次のとおりです。
$ for a in one two
> do echo "test $a"
> done
test one
test two
次の場合、履歴は1行に縮小されますcmdhist is set
。
$ shopt -p cmdhist lithist
shopt -s cmdhist
shopt -u lithist
$ history 3
24 for a in one two; do echo "test $a"; done
25 shopt -p cmdhist lithist
26 history 3
ある時点で、.clearを使用して(メモリから)履歴を消去したため、各コマンドの番号が変更されましたhistory -c
。
cmdhistをオフにすると、次のメッセージが表示されます。
$ shopt -u cmdhist
$ for a in one two
> do echo "test $a"
> done
test one
test two
$ history 5
5 shopt -u cmdhist
6 for a in one two
7 do echo "test $a"
8 done
9 history 5
各行(完全なコマンドではない)は、レコード内の別々の行に表示されます。
設定されていてもlithist
:
$ shopt -s lithist
$ for a in one two
> do echo "test $a"
> done
test one
test two
$ history 5
12 shopt -s lithist
13 for a in one two
14 do echo "test $a"
15 done
16 history 5
ただし、両方が設定されている場合:
$ shopt -s cmdhist lithist
$ for a in one two
> do echo "test $a"
> done
$ history 5
23 history 15
24 shopt -p cmdhist lithist
25 shopt -s cmdhist lithist
26 for a in one two
do echo "test $a"
done
27 history 5
コマンドはfor
複数行のコマンドで保存され、セミコロン(;
)の代わりに「改行」文字を使用します。上記のlithistが設定されていない場合と比較してみてください。
ディスク
上記の内容はすべて、シェルメモリに保存されたコマンドのリストを使用して解釈されます。ディスクにコマンドが書き込まれませんでした。 (既定値) ファイルは~/.bash_history
変更されません。
このファイルは、実行中のシェルが終了すると変更されます。この時点で、履歴はファイルを上書きするか(histappend
設定されていない場合)追加されます。
コマンドをディスクに送信するには、次のものが必要です。このセットを持って:
export PROMPT_COMMAND='history -a'
これにより、各コマンドラインが各新しいコマンドラインのファイルに追加されます。
それでは、cmdhistとlithistについて話しましょう。状況は見えるほど単純ではありません。でも心配しないでください。すぐにすべてが明確になります。
以下のすべてのコマンドを入力するのに時間がかかったとします(ショートカットなし、エイリアスなし、機能なし、実際のコマンドが必要です。申し訳ありません)。
まず、メモリ(history -c
)とディスク(バックアップする)(history -w
)次に3回試してください。
- デフォルト値のcmdhist(設定)とlithist(未設定)を使用します。
- 同時設定
- どちらも設定されていません。
- unset cmdhistでlithistを設定することは意味がありません(テストできます)。
実行するコマンドのリスト:
$ history -c ; history -w # Clear all history ( Please backup).
$ shopt -s cmdhist; shopt -u lithist
$ for a in one two
> do echo "test $a"
> done
$ shopt -s cmdhist; shopt -s lithist
$ for a in one two
> do echo "test $a"
> done
$ shopt -u cmdhist; shopt -u lithist
$ for a in one two
> do echo "test $a"
> done
あなたは(メモリから)次のように終わります:
$ history
1 shopt -s cmdhist; shopt -u lithist
2 for a in one two; do echo "test $a"; done
3 shopt -s cmdhist; shopt -s lithist
4 for a in one two
do echo "test $a"
done
5 shopt -u cmdhist; shopt -u lithist
6 for a in one two
7 do echo "test $a"
8 done
9 history
3 つの複数行コマンドは次のように終了します。
- 2行目の1つ(1行、1コマンド)。
- 4行で示された複数行の1つ(複数行の1つのコマンド)
- 6から8まで番号が付けられた複数行のうちの1つ
さて、さて、ファイルで何が起こっていますか?もう言ってたけど…
最後にファイルから:
簡単です。ファイルに書き込んで猫を送って確認してください。
$ history -w ; cat "$HISTFILE"
shopt -s cmdhist; shopt -u lithist
for a in one two; do echo "test $a"; done
shopt -s cmdhist; shopt -s lithist
for a in one two
do echo "test $a"
done
shopt -u cmdhist; shopt -u lithist
for a in one two
do echo "test $a"
done
history
history -w ; cat "$HISTFILE"
行番号もなくコマンドだけがあり、複数行が始まり終わる場所を知る方法はありません。複数行があっても判断する方法はありません。
実際、上記のようにコマンドがファイルに書き込まれると、ファイルを再読み込みすると、複数行に関するすべての情報が失われます。
区切り文字(改行文字)は1つだけで、各行はコマンドで再度読み取られます。
解決策はありますか?はい、追加の区切り文字を使用します。
HISTTIMEFORMATがまさにそのようなことをします。
過去の時間形式
この変数を値に設定すると、各コマンドが実行された時間は、コメント()文字の後にエポック(たとえば、常に秒)以降の秒数でファイルに保存されます#
。
変数を設定してファイルを書き換えると、次のような結果が~/.bash_history
得られます。
$ HISTTIMEFORMAT='%F'
$ history -w ; cat "$HISTFILE"
#1490321397
shopt -s cmdhist; shopt -u lithist
#1490321397
for a in one two; do echo "test $a"; done
#1490321406
shopt -s cmdhist; shopt -s lithist
#1490321406
for a in one two
do echo "test $a"
done
#1490321418
shopt -u cmdhist; shopt -u lithist
#1490321418
for a in one two
#1490321418
do echo "test $a"
#1490321420
done
#1490321429
history
#1490321439
history -w ; cat "$HISTFILE"
#1490321530
HISTTIMEFORMAT='%FT%T '
#1490321571
history -w ; cat "$HISTFILE"
これで、どこでどの行が複数行なのかがわかります。
この形式は、'%FT%T '
History コマンドを使用した場合のみ時間を表示します。
$ history
1 2017-03-23T22:09:57 shopt -s cmdhist; shopt -u lithist
2 2017-03-23T22:09:57 for a in one two; do echo "test $a"; done
3 2017-03-23T22:10:06 shopt -s cmdhist; shopt -s lithist
4 2017-03-23T22:10:06 for a in one two
do echo "test $a"
done
5 2017-03-23T22:10:18 shopt -u cmdhist; shopt -u lithist
6 2017-03-23T22:10:18 for a in one two
7 2017-03-23T22:10:18 do echo "test $a"
8 2017-03-23T22:10:20 done
9 2017-03-23T22:10:29 history
10 2017-03-23T22:10:39 history -w ; cat "$HISTFILE"
11 2017-03-23T22:12:10 HISTTIMEFORMAT='%F'
12 2017-03-23T22:12:51 history -w ; cat "$HISTFILE"
13 2017-03-23T22:15:30 history
14 2017-03-23T22:16:29 HISTTIMEFORMAT='%FT%T'
15 2017-03-23T22:16:31 history
16 2017-03-23T22:16:35 HISTTIMEFORMAT='%FT%T '
17 2017-03-23T22:16:37 history
答え2
これは複数行のコマンドではないようです(あなたがリターンをエスケープしたため)。実際の報酬があることをするならば違いがあります。
$ for i in /tmp/g*
> do echo $i
> done
/tmp/gigabyte
$ shopt -s lithist
$ for i in /tmp/g*
> do echo $i
> done
/tmp/gigabyte
$ history
[...]
517 for i in /tmp/g* ; do echo $i ; done
518 shopt -s lithist
519 for i in /tmp/g*
do echo $i
done
520 history
答え3
iTermは複数行のコマンドを完全に処理し、複数行のコマンドを1つのコマンドとして保存し、++を使用してCmd履歴を閲覧できます。より多くのiTermのヒントをご覧ください:Shift;iTermで効果的に作業する
答え4
私は努力したshopt -s lithist cmdhist
。
ただし、ログアウトおよびログイン後も履歴リカバリは~/.bash_history
まだ複数行に分かれています。
1953 2019-05-23 16:57:53 shopt -s cmdhist; shopt -s lithist
1954 2019-05-23 16:57:58 for i in 1 2 3
1955 2019-05-23 16:58:34 do echo $i
1956 2019-05-23 16:58:34 done
1957 2019-05-23 16:58:08 history 5
1958 2019-05-23 16:58:27 history -a
1959 2019-05-23 16:54:12 history 10 | less
この動作は予想されますか?
私が持っているものは次のとおりです~/.bash_history
。
#1558601873
shopt -s cmdhist; shopt -s lithist
#1558601878
for i in 1 2 3
do echo $i
done
#1558601888
history 5
#1558601907
history -a
#1558601652
history 10 | less
解決策
以前の ~/.bash_history を削除して問題を解決し、ログアウトしてログインした後も複数行の履歴が正常に機能しました。
1 2019-06-12 13:53:11 \rm .bash_history
2 2019-06-12 13:53:27 fx mcd
3 2019-06-12 13:53:28 mcd ()
{
mkdir $@;
cd $1
}
4 2019-06-12 14:55:14 nmcli-restart-hotspot -s
5 2019-06-12 21:34:35 ssh lab
6 2019-06-12 23:38:45 history | less