[bash] Fastest way(s) to move the cursor on a terminal command line?

What is the best way to move around on a given very long command line in the terminal?

Say I used the arrow key or Ctrl-R to get this long command line:

./cmd --option1 --option2 --option3 --option4 --option5 --option6 --option7 --option8 --option9 --option10 --option11 --option12 --option13 --option14 --option15 --option16 --option17 --option18 --option19 --option20 --option21 --option22 --option23 --option24 --option25 --option26 --option27 --option28 --option29 --option30 --option31 --option32 --option33 --option34 --option35 --option36 --option37 --option38 --option39 --option40 --option41 --option42 --option43 --option44 --option45 --option46 --option47 --option48 --option49 --option50 

Now I need to move (starting from the beginning or the end of the line) the cursor to --option25 to modify something there.

What is the fastest way to get there? What I usually do is Ctrl-A to get to the beginning and then repeatedly Alt-F to move forward, word by word (or Ctrl-E to go the end and Alt-B to then go backward). But on a long line that takes too much time. There must be a way to search and jump directly to the part I need to modify, e.g. option25?

This question is related to bash terminal window

The answer is


One option is to use M-x shell in emacs. That provides all editing facilities and keystrokes that emacs has, so C-s can be used to search the text option25, for example.

(But I'd still prefer to be in the real terminal shell instead if someone can point me to good search and edit facilities.)


I made a script to make the command line cursor move on mouse click :

  1. Enable xterm mouse tracking reporting
  2. Set readline bindings to consume the escape sequence generated by clicks

It can be found on github

More info on another post

Will work if echo -e "\e[?1000;1006;1015h" # Enable tracking print escape sequences on terminal when clicking with mouse


To be clear, you don't want a "fast way to move the cursor on a terminal command line". What you actually want is a fast way to navigate over command line in you shell program.

Bash is very common shell, for example. It uses Readline library to implement command line input. And so to say, it is very convenient to know Readline bindings since it is used not only in bash. For example, gdb also uses Readline to process input.

In Readline documentation you can find all navigation related bindings (and more): http://www.gnu.org/software/bash/manual/bash.html#Readline-Interaction

Short copy-paste if the link above goes down:

Bare Essentials

  • Ctrl-b Move back one character.
  • Ctrl-f Move forward one character.
  • [DEL] or [Backspace] Delete the character to the left of the cursor.
  • Ctrl-d Delete the character underneath the cursor.
  • Ctrl-_ or C-x C-u Undo the last editing command. You can undo all the way back to an empty line.

Movement

  • Ctrl-a Move to the start of the line.
  • Ctrl-e Move to the end of the line.
  • Meta-f Move forward a word, where a word is composed of letters and digits.
  • Meta-b Move backward a word.
  • Ctrl-l Clear the screen, reprinting the current line at the top.

Kill and yank

  • Ctrl-k Kill the text from the current cursor position to the end of the line.
  • M-d Kill from the cursor to the end of the current word, or, if between words, to the end of the next word. Word boundaries are the same as those used by M-f.
  • M-[DEL] Kill from the cursor the start of the current word, or, if between words, to the start of the previous word. Word boundaries are the same as those used by M-b.
  • Ctrl-w Kill from the cursor to the previous whitespace. This is different than M- because the word boundaries differ.
  • Ctrl-y Yank the most recently killed text back into the buffer at the cursor.
  • M-y Rotate the kill-ring, and yank the new top. You can only do this if the prior command is C-y or M-y.

M is Meta key. For Max OS X Terminal you can enable "Use option as meta key" in Settings/Keyboard for that. For Linux its more complicated.

Update

Also note, that Readline can operate in two modes:

  • emacs mode (which is the default)
  • vi mode

To switch Bash to use vi mode:

$ set -o vi

Personaly I prefer vi mode since I use vim for text editing.

Bonus

In macOS Terminal app (and in iTerm too) you can Option-Click to move the cursor (cursor will move to clicked position). This even works inside vim.


After running the command once, run fc

It will launch $EDITOR with the previous command, then you can use your regular editor to modify the command. When you save and exit, the file will be executed.

..but, as Pax said - the command line isn't particularly good for editing absurdly long lines - why not make the command into a script?


It might not be the fastest, but this need to be here, some reading about ANSI cursor movements

ANSI escape sequences allow you to move the cursor around the screen at will. This is more useful for full screen user interfaces generated by shell scripts, but can also be used in prompts. The movement escape sequences are as follows:

- Position the Cursor:
  \033[<L>;<C>H
     Or
  \033[<L>;<C>f
  puts the cursor at line L and column C.
- Move the cursor up N lines:
  \033[<N>A
- Move the cursor down N lines:
  \033[<N>B
- Move the cursor forward N columns:
  \033[<N>C
- Move the cursor backward N columns:
  \033[<N>D

- Clear the screen, move to (0,0):
  \033[2J  or \033c
- Erase to end of line:
  \033[K

- Save cursor position:
  \033[s
- Restore cursor position:
  \033[u

(...)

Try putting in the following line of code at the prompt (it's a little clearer what it does if the prompt is several lines down the terminal when you put this in): echo -en "\033[7A\033[1;35m BASH \033[7B\033[6D" This should move the cursor seven lines up screen, print the word " BASH ", and then return to where it started to produce a normal prompt.


Examples:

Move the cursor back 7 lines:

echo -e "\033[7A"

Move the cursor to line 10, column 5:

echo -e "\033[10;5H"

Quickly echo colors codes, to colorize a program:

echo -e "\033[35;42m" ; ifconfig

Use the mouse

Sometimes, the easiest way to edit a commandline is using a mouse. Some previous answers give a command to open your current line in your $EDITOR. For me (zhs with grml config) that combination is Alt+e. If you enable mouse in your editor, you can make use of it.

To enable mouse in Vim, add this to your ~/.vimrc

set mouse=a
set ttymouse=xterm2

If you then want to do a text selection in terminal (instead of passing the mouseclick to vim), hold Shift when you click; this is terminal specific, of course.

Sysadmins should not be afraid of the mouse.


I tend to prefer vi editing mode (since those keystrokes are embedded into my spinal cord now (the brain's not used at all), along with the CTRL-K, CTRL-X from WordStar 3.3 :-). You can use the command line set -o vi to activate it (and set -o emacs to revert).

In Vi, it would be (ESC-K to get the line up first of course) "f5;;B" (without the double quotes).

Of course, you have to understand what's on the line to get away with this. Basically, it's

f5 to find the first occurrence of "5" (in --option5).
;  to find the next one (in --option15).
;  to find the next one (in --option25).
B  to back up to the start of the word.

Let's see if the emacs aficionados can come up with a better solution, less than 5 keystrokes (although I don't want to start a religious war).

Have you thought about whether you'd maybe like to put this horrendously long command into a script? :-)

Actually, I can go one better than that: "3f5B" to find the third occurrence of "5" then back up to the start of the word.


Use Meta-b / Meta-f to move backward/forward by a word respectively.

In OSX, Meta translates as ESC, which sucks.

But alternatively, you can open terminal preferences -> settings -> profile -> keyboard and check "use option as meta key"


Incremental history searching

in terminal enter:

gedit  ~/.inputrc

then copy paste and save

"\e[A": history-search-backward
"\e[B": history-search-forward
"\e[C": forward-char
"\e[D": backward-char

all you need to do to find a previous command is to enter say the first 2 or 3 letters and upward arrow will take you there quickly say i want:

for f in *.mid ; do timidity "$f"; done

all i need to do is enter

fo

and hit upward arrow command will soon appear


If you want to move forward a certain number of words, hit M-<n> (M- is for Meta and its usually the escape key) then hit a number. This sends a repeat argument to readline, so you can repeat whatever command you want - if you want to go forward then hit M-<n> M-f and the cursor will move forward <n> number of words.

E.g.

 $|echo "two three four five six seven"
 $ M-4
 (arg: 4) echo "two three four five six seven"
 $ M-f
 $ echo "two three four| five six seven"

So for your example from the cursor at the beginning of the line you would hit, M-26 M-f and your cursor would be at --option25| -or- from the end of the line M-26 M-b would put your cursor at --|option25


first: export EDITOR='nano -m'

then: CTRL+X CTRL+E in sequence.

You current line will open in nano editor with mouse enable. You can click in any part of text and edit

then CTRL+X to exit and y to confirm saving.


Hold down the Option key and click where you'd like the cursor to move, and Terminal rushes the cursor that precise spot.


In Cygwin, you can activate such feature by right-clicking the window. In the pop-up window, select Options... -> Mouse -> activate Clicks place command line cursor -> Apply.

From now on, simply clicking the left mouse button at some position within the command line will place the cursor there.


Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to terminal

Git is not working after macOS Update (xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools) Can't compile C program on a Mac after upgrade to Mojave Flutter command not found VSCode Change Default Terminal How to switch Python versions in Terminal? How to open the terminal in Atom? Color theme for VS Code integrated terminal How to edit a text file in my terminal How to open google chrome from terminal? Switch between python 2.7 and python 3.5 on Mac OS X

Examples related to window

CMD command to check connected USB devices Get viewport/window height in ReactJS the MySQL service on local computer started and then stopped AngularJS $watch window resize inside directive tkinter: Open a new window with a button prompt window.close() doesn't work - Scripts may close only the windows that were opened by it Send parameter to Bootstrap modal window? How do I insert a JPEG image into a python Tkinter window? Installing Python 2.7 on Windows 8 How do I get the offset().top value of an element without using jQuery?