Автозаполнение Bash выдает другое имя файла, чем ls

Автозаполнение Bash выдает другое имя файла, чем ls

Только что произошло нечто невероятно странное. Из-за серьезной опечатки я ввел

cp filename.xsl .^?~

Да, именно так, точка-каре-знак вопроса-тильда! Правда страннее вымысла.

Это становится еще страннее. Когда я печатаю

cat .

а затем нажмите TAB, я получаю

./    ../    .^?~

но когда я делаю ls -a, я получаю

.    ..    .?~

Наконец, когда я это сделаю,

rm .?~

команда удаления выдает мне следующее:

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

прежде чем успешно удалить его. Почему несостоятельность существования каретки?

решение1

Это связано с тем, что символ каретки часто используется для обозначения ctrlнажатия клавиши или в качестве управляющего символа.

Последовательность клавиш, которую вы на самом деле набрали, была следующей:

cp filename.xsl .ctrl+Vbackspace~Enter

Вероятно, вы пытались скопировать файл в свой домашний каталог ( ~). Вы можете повторить это, набрав ctrl+ Vbackspace. Вы увидите ^?напечатанное на экране.

Вы можете просматривать файлы с непечатаемыми символами, преобразованными вC-стильэкранируется следующим образом (главное — флаг -b, но поскольку ваш файл начинается с точки, вам -aтакже понадобится:

$ ls -ab
.  ..  .\177~

Без -bвы увидите его .?~не потому, что он просто опускает ^, а потому, что любой непечатаемый символ отображается как ?. Попробуйте touchctrl+ VEnterfooEnterи затем ls. Файл, который вы увидите, будет ?foo. Затем ls -bотобразится \rfoo.

Так что когда вы rm .?~это соответствует, потому что в этом случае ?введенный вами символ интерпретируется оболочкой как подстановочный знак для соответствия любому отдельному символу, а не конкретно фактическому знаку вопроса. Вы сделали rmпсевдоним, rm -iпоэтому он подтверждает ваше действие, и когда это происходит, он показывает код выхода в стиле C.

решение2

Странный символ в имени файла (на который указывает rm) — это символ 0177( 0x7Fh / 127d ). Это и есть Delсимвол.

Автодополнение Bash, похоже, не справляется с этим последовательно. lsвыводит a ?для непечатаемых символов (по умолчанию). Попробуйте:

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

rmоказывается полезным и выводит свое восьмеричное значение.

решение3

Когда вы нажимаете TAB, и оболочка выполняет своего рода угадывание имени файла, она печатает два символа, «^» и «?» для байта с восьмеричным значением 177. Вы можете получить имя файла с байтом этого значения, нажав ctrl-V, а затем shift-ctrl-? (три клавиши одновременно) для проверки.

Имя файла было не точка-каре-знак вопроса-тильда, а точка-восьмеричное 177-тильда. Разные программы представляли байт с восьмеричным значением 177 разными способами.

Связанный контент