zshに履歴の1行を入力してそれを実行しようとしています。
cat ~/.zsh_history | cut -d ';' -f 2 | sk --tac | zsh
インタラクティブに行を選択した場合、たとえばsk
。PATH
man zsh
ck
ただし、拡張機能を実行するのではなく、同じエイリアスがあると、cd .. && ls
「コマンドが見つかりません」というエラーが発生します。
編集:また、次のように入力すると:
echo "cd .. && ls" | zsh
親ディレクトリで実行した結果を印刷しますls
が、コマンドが終了するとサブディレクトリの元のプロンプトに戻ります。プロンプトに手動で入力し、Enterキーを押したようにzshがパイプでリンクされたコンテンツを処理する方法はありますか?
答え1
コードをパイプしてzsh
別のプロセスでコードを実行します。このプロセスには、エイリアスや関数(未読.zshrc
)などの対話型設定はなく、シェル変数や現在のシェルの他の状態もありません。他のプロセスが終了すると、そのプロセスの状態(現在のディレクトリなど)が失われます。
eval
現在のシェルプロセスでコードを実行するには、そのコードを組み込み関数に引数(入力ではない)として渡します。
eval "$(<~/.zsh_history cut -d ';' -f 2 | sk --tac)"
ただし、履歴項目を選択する特定のユースケースには異なるアプローチがあります。これfc
組み込み。次のコマンドは、一時fcedit_sk
ファイルの名前である1つの引数を使用して関数を実行します。この関数が呼び出されると、ファイルにはすべての履歴エントリ(最新のエントリを表す${${(kn)history}[1]}
最も古いエントリのインデックス-1
)が含まれます。関数が返されると、zshはプロンプトで入力したようにファイルに含まれているすべてを実行します。
fc -e fcedit_sk ${${(kn)history}[1]} -1
ファイルの内容を呼び出し、その出力をファイルに書き戻す関数を作成しますfcedit_sk
。sk
それで、sk
これより簡単な方法があるかどうかわかりません。
fcedit_sk () {
local output
output=$(sk --tac <$1)
if (($?)); then
echo >|$1 # Cancelled
else
print -lr -- $output >|$1
fi
}