5

An incredibly strange thing just happened. Through a serious typo, I entered

cp filename.xsl .^?~

Yeah, that's right, dot-caret-questionmark-tilde! Truth is stranger than fiction.

It gets weirder. When I type

cat .

and then hit TAB, I get

./    ../    .^?~

but when I do an ls -a, I get

.    ..    .?~

Finally, when I do

rm .?~

the remove command prompts me thus:

rm: remove write-protected regular file `.\177~'?

before successfully removing it. Why the descrepency of the existence of the caret?

3 Answers 3

10

It's because the caret is often used to signify the ctrl key having been pressed, or that it's otherwise a control character.

The key sequence that you actually typed was this:

cp filename.xsl .ctrl+Vbackspace~Enter

You were presumably trying to copy the file to your home directory (~). You can repeat this by typing ctrl+Vbackspace. You'll see ^? printed on the screen.

You can view files with non-printing characters converted to C-style escapes like this (it's the -b flag that's important, but since your file begins with a dot you'll need -a as well:

$ ls -ab
.  ..  .\177~

Without the -b you only see it as .?~ not because it's simply omitting the ^, but because any non-pritable character is displayed as ?. Try touchctrl+VEnterfooEnter and then ls. The file you'll see will be ?foo. Then ls -b will show \rfoo.

So when you rm .?~ it is matching because in this case the ? you typed is interpreted by the shell as a globbing wildcard to match any single character, not specifically an actual question mark. You have rm aliased to rm -i so it's confirming your action and when it does it shows the C-style escape code.

1
  • Wow! Yes, I was trying to copy it to my home directory... I'm shocked you figured that out given how many extra keys I hit! The other answers were good, but this is excellent. +1
    – Kazark
    Commented Jul 3, 2012 at 21:01
2

The strange character you have in that filename (as indicated by rm) is character 0177 (0x7Fh/127d). That's the Del character.

Bash autocompletion seems to be failing to handle it consistently. ls prints a ? for unprintable characters (by default). Try:

$ echo a > .$'\x7f'~
$ ls -b .??
.\177~

rm is being helpful and prints its octal value.

2

When you hit TAB, and the shell does some kind of filename guessing, it's printing two characters, '^' and '?' for the byte valued octal 177. You can get a filename with a byte of that value by hitting ctrl-V then shift-ctrl-? (three keys at once) for testing.

The file name wasn't dot-caret-questionmark-tilde, but rather dot-octal 177-tilde. Different programs chose to represent the octal-177 valued byte different ways.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .