Sample Header Ad - 728x90

Need Help Understanding script that reads output of cursor position ANSI escape code

0 votes
1 answer
73 views
I have this code, which does what I want, but I don't entirely understand it:
#!/usr/bin/env bash

echo -ne "\033[6n"            # Ask the terminal to print out the cursor's position
                              # The response looks like ^[[n;mR - where n = row, m = col
read -s -d\[ garbage          # Read the response silently, discarding the first part of the response, leaving n;mR
read -s -d ';' row            # Read some more, silently, until we get to the character ';', storing what we read in the variable "row"
read -s -d R col              # Read some more, silently, until we get to the character 'R', storing what we read in the variable "col"
echo "The (row,col) coords are ($row,$col)"
If I run echo -ne "\033[6n" at a shell prompt, I get kind of what the comments say I'll get, but not exactly:
$ echo -ne "\033[6n"
^[[11;1R$ ;1R
If I put that in a script (I'll call it "splurt.sh"), and run the script, the results are the same:
#!/usr/bin/env bash

echo -ne "\033[6n"

echo
$ ./splurt.sh 

^[[16;1R$ ;1R
So at this point, I just accept that the line works, even if it's not displaying as I would expect it to. But then comes the next line:
read -s -d\[ garbage          # Read the response silently, discarding the first part of the response, leaving n;mR
I kind of understand that "read" reads input from the console (keyboard, usually, I would think), but somehow it seems to be reading from the console's monitor? I understand the "-s" means to read the console silently, but I don't quite comprehend that. I put this into my short script:
#!/usr/bin/env bash

echo -ne "\033[6n"
read -s -d\[ garbage
echo
and I get:
$ ./splurt.sh 

$ 25;1R
If I leave out the "-s", I get:
$ ./splurt.sh 
^[[27;1R
$ 27;1R
So I can see that the "-s" does prevent the echo of "^[[27;1R" to the screen, but I don't grok that, because I thought the echo -n e "\033[6n" had already printed that out to the screen (although apparently not, because I don't see it until the "read" reads it?). I do understand (finally! I understand something!) that the "-d" only reads up to the specified delimiter (usually a newline, as I understand it, unless specified by the "-d"), and that what gets read is placed into the variable "garbage" (which is henceforth ignored), but I don't understand how "\[" causes the read to go all the way through "^[[", instead of stopping at "^[", to leave "[27:1R" instead of what it actually leaves of "27:1R". And then the rest of the script I have a fairly good grip on, methinks. Anyone want to take a stab at helping me to understand better what's going on? Thanks!
Asked by user153064 (13 rep)
Jul 8, 2025, 01:28 PM
Last activity: Jul 8, 2025, 08:05 PM