Какие символы нужно экранировать в файлах без кавычек?

12

У меня есть основанная на браузере оболочка / терминал, которая выполняет команды bash, и я экранирую пробелы, но оказывается, что скобки также должны быть экранированы. Какие еще символы необходимо экранировать для имен файлов, которые не в кавычках?

jcubic
источник
Не совсем понятно, что вы пытаетесь сделать. И при чем тут автодополнение?
Майкл Вёрс
@MichaelVehrs У меня есть команда mv filename filename-fooв bash, какие символы мне нужно экранировать, кроме пробелов и скобок?
jcubic
@MichaelVehrs удалил упоминание автозаполнения.
jcubic
По сути, все метасимволы оболочки, такие как пробелы, глобусы оболочки, события истории. По этой причине, вы должны процитировать все имя файла, а не спасаясь отдельными символы: mv "$filename" "$newname".
Майкл Vehrs
@MichaelVehrs Я знаю, что цитирование решит проблему с экранированием, но мне нужно использовать имя файла без кавычек. У меня есть эмулятор терминала, и он должен работать, когда пользователь не использует кавычки.
17

Ответы:

22

Простое решение состоит в том, чтобы поместить одну кавычку ( ') в начале и другую одинарную кавычку в конце и заменить каждый 'символ в имени файла последовательностью из 4 символов '\''. Все символы теряют свое специальное значение внутри строки в одинарных кавычках, кроме 'самого себя, который отмечает конец строки. Последовательность '\''заканчивается литералом в одинарных кавычках, сразу же следует одинарная кавычка и открывает новый литерал в одинарных кавычках. Таким образом, имя файла

This file's name has some weird characters!
Will you manage to escape them?

можно процитировать следующим образом:

somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'

Двойные кавычки имеют более сложные правила экранирования и не позволяют вам включать восклицательный знак, !если подстановка истории активирована, поэтому я не буду их рассматривать дальше.

Альтернативный подход заключается в защите символов с помощью обратной косой черты. Это работает для каждого персонажа, кроме перевода строки; для новой строки единственное решение - поместить его в одинарные кавычки (или двойные кавычки). Если вы хотите минимизировать количество обратных слешей, чтобы представить имя в кавычках пользователю, вы можете ограничить его местами, где необходим обратный слеш; однако чем больше обратной косой черты вы пропускаете, тем больше рискуете забыть ту, которая нужна. Буквы, цифры и не-ASCII символы всегда в порядке. Цитируйте пробел и пунктуацию всякий раз, когда вы не уверены.

В обычной оболочке (ksh, bash или zsh) вам необходимо заключать в кавычки следующие символы, по крайней мере, при некоторых обстоятельствах.

  • Пробелы (пробел, табуляция, новая строка - запоминание того, что новые строки нельзя заключать в кавычки).
  • ! - расширение истории.
  • " Синтаксис оболочки.
  • #- комментарий начинается, когда ему предшествует пробел; зш подстановочные знаки.
  • $ Синтаксис оболочки.
  • & Синтаксис оболочки.
  • ' Синтаксис оболочки.
  • (- даже в середине слова: расширенные глобусы ksh (также доступны в bash и zsh); зш подстановочные знаки.
  • )(см. ()
  • * - подстановочный знак.
  • , - только внутри расширения скобки.
  • ; Синтаксис оболочки.
  • < Синтаксис оболочки.
  • = - в zsh, когда оно находится в начале имени файла (расширение файла с поиском PATH).
  • > Синтаксис оболочки.
  • ? - подстановочный знак.
  • [ - подстановочный знак.
  • \ Синтаксис оболочки.
  • ] - вы можете оставить это без кавычек.
  • ^- расширение истории; зш подстановочный знак.
  • ` Синтаксис оболочки.
  • { Расширение скобки.
  • | Синтаксис оболочки.
  • } - необходимо экранировать в zsh, другие оболочки более мягкие, когда нет соответствующей открывающей скобки.
  • ~- расширение домашнего каталога, когда оно находится в начале имени файла; zsh подстановочный знак; всегда безопасно, когда это последний символ.

Еще несколько символов могут требовать специальной обработки иногда:

  • -не является особенным для оболочки, но когда он находится в начале аргумента команды, он указывает опцию. Он не может быть защищен кавычками, поскольку специальная обработка находится в команде, а не в оболочке. Чтобы защитить имя файла, которое начинается с -, вы можете поставить ./перед ним - таким образом, это все тот же файл, но аргумент больше не начинается с -.
  • .сам по себе не является особенным, но файлы *точек по умолчанию исключаются из глобусов.
  • :не является особенным для оболочки, но некоторые команды анализируют его специально, например, для указания удаленного файла ( hostname:filename). Обратитесь к документации команды, чтобы узнать, как справиться с именами файлов, содержащими двоеточия.

¹ Если пользователь не настроил альтернативные символы расширения истории. Некоторые оболочки позволяют это. Это еще одна причина использовать одинарные кавычки, а не обратную косую черту.

Жиль "ТАК - перестань быть злым"
источник
Символы новой строки, по крайней мере, LFтолько, могут быть заключены с обратной косой чертой в некоторых оболочках.
iBug
@iBug Нет. В любой sh-подобной оболочке обратная косая черта + новая строка расширяется до пустой строки, а не до новой строки.
Жиль "ТАК - перестань быть злым"
Это хороший ответ, спасибо. Есть ли ссылка на то, где эта информация «официально» доступна?
Слэшмайс
1
@slashmais Какая информация? Синтаксис языка оболочки «официально» доступен в различных руководствах и спецификациях, но перейти оттуда к точному определению, какие символы нужно указывать, а где нет, не совсем понятно.
Жиль "ТАК - перестань быть злым"
1
Я также нашел это: tecmint.com/manage-linux-filenames-with-special-characters - это не так компактно, как ваш список, но есть множество примеров. (
Постепенно