Оболочка Bash / C: есть ли недостатки в экранировании всех символов пути к файлу? - PullRequest
2 голосов
/ 16 марта 2012

Есть ли какие-либо недостатки в экранировании всех символов пути к файлу Unix? Под недостатками я имею в виду: ограничение любого рода, случаи, когда путь к файлу не может быть интерпретирован оболочкой Unix и т. Д..

Пример:

/my/path/to/file.txt 

становится

\/\m\y\/\p\a\t\h\/\t\o\/\f\i\l\e\.\t\x\t

Примечания:

  • Читаемость не является проблемойздесь для автоматизации.
  • Оболочка: Bash Shell и C Shell

Причина:

Я пишу небольшое приложение на Pythonтранскодировать изображения и видео, используя различные командные строки в Unix's Bash Shell (FFMPEG, Handbrake, FFPROBE, ImageMagick для идентификации и преобразования).У некоторых путей к файлам есть пробелы, символы скобок и т. Д. Имена файлов с такими символами обычно разбивают командные строки в этих инструментах, если эти символы не экранированы должным образом.Я бы предпочел найти решение, которое применимо в целом, а не экранировать только несколько символов, таких как пробелы, скобки и т. Д. Особенно в контексте, где я не контролирую имена файлов и пытаюсь сделать свое приложениемаксимально надежный при работе с именами файлов со специальными символами.Следовательно, решение избежать всего.

Результаты:

Я избежал всех символов, и у меня не возникло никаких проблем, кроме как в случае модулей / функций Python OS, которые ужеобрабатывать имя файла для конкретных ОС (в этом случае экранирование всех символов является проблемой, но я ожидал этого).Поэтому я бы сказал, что экранирование всех символов не имеет никаких недостатков (кроме случая, который я упоминал ранее).

С уважением,

symbion

Ответы [ 3 ]

2 голосов
/ 16 марта 2012

Пример, который вы дали, не сработает, потому что в целом один символ, которому предшествует обратная косая черта, не экранирует символ, но вводит новое значение.Например, \n не является n экранированным, а символом новой строки.

Другой способ экранирования специальных символов - заключать все в кавычки, например,

"/my/path/to/file.txt"

.необходимо экранировать символ кавычки ", т.е. \".В качестве альтернативы вы можете использовать один символ кавычки вокруг пути, например,

'/my/path/to/file.txt'

То же самое применимо и здесь, если путь содержит ', вам необходимо его избежать.

1 голос
/ 21 марта 2012

В такой программе вас волнуют две вещи:

  1. Функциональность
  2. читаемость

Первый пункт очевиден - вам нужно передать правильную строку из одной программы в другую. В Bash есть только два способа написать абсолютно любое имя файла в скрипте. Например, для файла с таким названием:

$ echo -n $'\a\b\E\f\r\t\v\'"\360\240\202\211 \n' | uniname -pcb
UTF-32   encoded as     glyph   name
000007   07                     BELL
000008   08                     BACKSPACE
00001B   1B                     ESCAPE
00000C   0C                     FORM FEED (FF)
00000D   0D                     CARRIAGE RETURN (CR)
000009   09                     CHARACTER TABULATION
00000B   0B                     LINE TABULATION
000027   27             '      APOSTROPHE
000022   22             "      QUOTATION MARK
020089   F0 A0 82 89    ?      Unknown character in range CJK Unified Ideographs Extension B
000020   20                     SPACE
00000A   0A                     LINE FEED (LF)

Существует пять способов написания строк в Bash, один из которых ($"") не подходит для этой цели:

  • Литеральная строка с escape-символами. нет способа включить литерал перевод строки таким образом , так что это не так. Пример:

    $ foo=bar
    $ baz
    No command 'baz' found, did you mean: ...
    $ foo=bar\
    > baz
    $ echo "$foo"
    barbaz
    $ foo=bar\nbaz
    $ echo "$foo"
    barnbaz
    $ foo=bar\\nbaz
    $ echo "$foo"
    bar\nbaz
    
  • Строка в одинарных кавычках . Эти не могут содержать другие одинарные кавычки , поэтому их нет.
  • Строка в двойных кавычках . Вы можете поместить в них что угодно, но вам нужно экранировать некоторых символов, если вы хотите, чтобы они были буквально представлены - простое предшествование каждому символу обратной косой чертой вряд ли даст желаемый результат. Кроме того, сложные символы, такие как BELL, должны быть включены как литерал , что делает его практически невидимым для человека, читающего сценарий или вывод.
  • ANSI-C Цитирование , показанное выше. Он также может содержать любой символ, но вы можете экранировать специальные символы, чтобы сделать строку более читабельной.

Из двух методов довольно ясно, что если вы хотите напечатать любое имя файла, вам следует использовать цитирование ANSI-C, если вы не знаете, что может содержать строка. Но если вы хотите всегда использовать «минимальное» экранирование, вы можете напечатать значение, используя printf %q - Сравните:

$ printf %q $'word'
word
$ printf %q $'space separated'
space\ separated
$ printf %q $'newline\nembedded'
$'newline\nembedded'
0 голосов
/ 17 марта 2012

Не совсем то, что вы просили, но может быть лучшим решением, учитывая добавленную причину: модуль pipes в python имеет функцию под названием quote, которую вы можете импортировать и которая указывает кавычки для команд оболочки:

$ python
...
>>> from pipes import quote
>>> quote('filename')
'filename'
>>> quote('filename with "funny"\tcharacters')
'\'filename with "funny"\tcharacters\''
>>> >>> quote("filename with 'single quotes'")
'\'filename with \'"\'"\'single quotes\'"\'"\'\''
>>>
...