다양한 텍스트 파일에 수백 개의 테스트되고 시도된 명령과 조각이 저장되어 있습니다. 재사용해야 할 때는 찾아서 명령줄에 복사하여 붙여넣습니다. 신뢰할 수는 있지만 이는 서투른 접근 방식입니다. 이와 대조적으로, 히스토리 파일에서 이전 명령을 명령줄로 직접 검색하여 편집 및 사용을 위해 준비할 수 있습니다. 이 기능을 에뮬레이션하고 자체 명령 세트를 사용하려면 어떻게 해야 합니까?
fzf를 사용하여 검색하고 내 명령을 찾아서 기록 파일에 추가하는 스크립트가 있습니다. 이것은 훌륭하게 작동합니다. 그러나 그것은 역사적 문서를 혼란스럽게 만듭니다.
이것은 내 스크립트입니다.
find ~ -type f | fzf --preview-window=up:50% --header "ENTER:less; ^s:snip to history" --bind "enter:execute(less {})" --bind "ctrl-s:execute(cat {} | fzf -m --preview-window=:hidden >>~/.bash_history)"; history -n
답변1
대화형 Bash를 위한 빠르고 간단한 설정(my bash --version
print 5.2.15
):
원하는 (한 줄) 명령을
~/.commands
.다음 도우미 함수를 정의합니다.
_get_command () { READLINE_LINE="$(<~/.commands fzf -1 --query="$READLINE_LINE")" && READLINE_POINT="${#READLINE_LINE}" }
키에 바인딩(키 시퀀스):
bind -x '"\C-x\C-r":_get_command'
Ctrl+ x, Ctrl+ 를 사용하여 시작하세요 r.
노트:
READLINE_POINT="${#READLINE_LINE}"
커서는 맨 끝에 위치해야 합니다. Bash 5는 문자 길이를 원하고 위 코드는 작동하지만 Bash 4는 바이트를 원합니다. Bash 4에서 ASCII가 아닌 텍스트를 처리하려면 다음을 사용하십시오.READLINE_POINT="$(printf '%s' "$READLINE_LINE" | wc -c)"
(나는 -에서왔다이 답변).
~/.commands
각 명령에 대해 원하는 커서 위치를 지정하거나 인코딩하기 위해 자신만의 형식을 만들 수 있기 때문입니다 . 귀하의 형식에 따라 설정할 수 있도록 도우미 기능이 향상되었습니다READLINE_LINE
.READLINE_POINT
반면에
~/.commands
저장 전용 리터럴 명령은 다음과 같습니다.단순한그리고--query="$READLINE_LINE"
.여러 줄 명령의 경우
fzf --read0
및 에 null로 끝나는 항목이 필요합니다~/.commands
. 이 형식을 유지하는 것은 개행 문자로 끝나는 항목을 편집하는 것보다 더 어렵습니다.
위의 내용을 작성한 후 이 기능이 필요하다고 결정했습니다. 더 복잡한 솔루션은 다음과 같습니다 ~/.bashrc
.
export SNIPPETFILE
_del_snippet () {
SNIPPETFILE="${SNIPPETFILE:-"$HOME/.snippets"}"
printf '%s\0' "$1" | sort -zm -- "$SNIPPETFILE" - | uniq -zu >"$SNIPPETFILE"~ \
&& mv -- "$SNIPPETFILE"~ "$SNIPPETFILE"
cat -- "$SNIPPETFILE"
}
export -f _del_snippet
_get_snippet () {
SNIPPETFILE="${SNIPPETFILE:-"$HOME/.snippets"}"
local line
line="$(<"$SNIPPETFILE" fzf -1 --read0 --query="$READLINE_LINE" \
--border top --border-label 'Enter to confirm, Ctrl+y to delete entry, Ctrl+c to abort' \
--bind 'ctrl-y:reload-sync(exec bash -c "_del_snippet \"\$1\"" bash {})')" \
&& READLINE_LINE="$line" \
&& READLINE_POINT="${#READLINE_LINE}"
}
bind -x '"\C-x\C-r":_get_snippet'
_put_snippet () {
[[ "$READLINE_LINE" =~ ^[[:space:]]*$ ]] && return 0
SNIPPETFILE="${SNIPPETFILE:-"$HOME/.snippets"}"
if
touch -- "$SNIPPETFILE" \
&& printf '%s\0' "$READLINE_LINE" | sort -zum -- "$SNIPPETFILE" - >"$SNIPPETFILE"~ \
&& mv -- "$SNIPPETFILE"~ "$SNIPPETFILE"
then
printf 'command stored in `%s'\''\n' "$SNIPPETFILE" >&2
else
printf 'storing in `%s'\'' failed\n' "$SNIPPETFILE" >&2
return 1
fi
}
bind -x '"\C-x\C-m":_put_snippet'
용법:
Ctrl+ x, Ctrl+를 사용하여 현재 명령줄을 저장합니다 m.
Ctrl+ x, Ctrl+를 사용하여 r저장된 명령 목록에서 선택합니다. 이미 입력한 내용과 정확하게 일치하는 항목이 있으면 명령줄로 이동됩니다. 더 많은 경우 대화식으로 선택할 수 있습니다.
대화형으로 선택할 때 Ctrl+는 y강조 표시된 항목을 제거합니다.
노트:
여러 줄 명령이 지원되지만 올바르게 저장하려면 클릭할 수 없습니다 Enter(따옴표 안이나 뒤
\
). 그렇지 않으면 보조 프롬프트가 나타납니다. 기록에서 여러 줄 명령을 가져오거나 Ctrl+ v, +를 눌러 Ctrl명령을 여러 줄로 만들어야 j보조 프롬프트가 나타나지 않고 계속 전체 명령을 편집할 수 있습니다. 그런 다음 Ctrl+ x, Ctrl+ 는 m전체 여러 줄 명령을 저장할 수 있습니다.이러한 줄을 대화형으로 선택하면 여러 줄 명령처럼 보이지 않지만 여러 줄로 명령줄에 표시됩니다.
여기에는 좋은 부작용이 있습니다. 레이블이 지정된 명령을 저장할 수 있습니다. 이것
# description (label) here : actual_command args
목록은 다음과 같습니다.
# description (label) here : actual_command args
하지만 선택한 후에는 작동합니다.
기본 파일은 입니다
$HOME/.snippets
.export
라는 변수를 설정하고 사용하여 다른 경로 이름을 사용할 수 있습니다SNIPPETFILE
. 뒤에 물결표가 있는 경로 이름(예:$HOME/.snippets~
)도 유지 관리에 사용됩니다.Bash 5.2.15에서 GNU 및 GNU로
sort
테스트되었습니다uniq
(이식 가능하지 않은 옵션 사용).여전히 오류가 있을 수 있습니다.
답변2
문제를 해결하려면 xdotool을 탐색해 볼 가치가 있습니다.
매뉴얼 페이지에 따르면:
xdotool을 사용하면 키보드 입력 및 마우스 활동을 프로그래밍 방식으로(또는 수동으로) 시뮬레이션하고 창을 이동하고 크기를 조정하는 등의 작업을 수행할 수 있습니다.
따라서 즐겨찾는 명령을 찾는 데 도움이 되는 별칭을 정의하고 xdotool에 이를 명령줄에 배치하도록 지시할 수 있습니다. 예를 들어:
$ alias my_command='stty -echo && xdotool type "$(cat any_list | fzf)" ; stty echo'
이렇게 하면 "any_list" 파일에서 텍스트 줄을 추출하여 명령줄에 배치할 수 있습니다. 해당 텍스트가 이전 명령 중 하나인 경우 해당 텍스트를 편집하고 실행할 수 있습니다.
현재 설정에 이미 xdotool이 있을 수 있습니다. 그렇지 않다면 다운로드하고 설치하는 것이 매우 쉽습니다.https://installati.one/install-xdotool-debian-12
답변3
존재하다 bash
,shell-expand-line
(키보드 단축키 M-C-e
, 일반적으로 ++ ALT) 는 "쉘처럼 줄을 확장합니다. 이는 모든 쉘 단어 확장뿐만 아니라 별칭 및 기록 확장도 수행합니다."CTRLe
따라서 원하는 것을 달성하는 가장 쉬운 방법은 명령줄에 삽입하려는 명령을 일부 변수에 할당하고 변수 이름을 쓴 다음 이 키 시퀀스를 눌러 내용을 확장하는 것입니다.
예를 들어:
$ COMMAND="echo hello world"
이제 명령줄에 변수 이름( $COMMAND
이 경우) 을 쓰고 ALT+ CTRL+ 를 누르세요 e. $COMMAND
현재 줄의 내용으로 자동으로 대체됩니다.
$ echo hello world
$(!!)
또는 시퀀스를 작성하고 클릭하여 명령줄을 이전 명령의 출력으로 바꿀 수 있습니다. 예를 들어:
$ grep ps .snippets
ps -fp $$
$ $(!!)
해당 지점에서 ALT+를 클릭하면 명령줄이 명령 출력으로 대체 CTRL됩니다 .egrep
$ ps -fp $$