Bash/C shell: Are there any drawbacks about escaping all characters of a file path? Bash/C shell: Are there any drawbacks about escaping all characters of a file path? unix unix

Bash/C shell: Are there any drawbacks about escaping all characters of a file path?


The example you've given won't work because in general a single character preceded by a backslash does not escape the character, but introduces a new meaning. \n for example is not n escaped, but the newline character.

Another way of escaping special characters is to enclose everything in quotes, e.g.

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

With this you only need to escape the quote character ", i.e. \". Alternatively, you can use a single quote character around the path, e.g.

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

Same applies here, if the path contains a ', you need to escape it.


What you care about in a program like this are two things:

  1. Functionality
  2. Readability

The first point is obvious - You need the correct string to be passed from one program to the other. In Bash there are only two ways you can write absolutely any filename in a script. Given for example a filename like this:

$ echo -n $'\a\b\E\f\r\t\v\'"\360\240\202\211 \n' | uniname -pcbUTF-32   encoded as     glyph   name000007   07                     BELL000008   08                     BACKSPACE00001B   1B                     ESCAPE00000C   0C                     FORM FEED (FF)00000D   0D                     CARRIAGE RETURN (CR)000009   09                     CHARACTER TABULATION00000B   0B                     LINE TABULATION000027   27             '      APOSTROPHE000022   22             "      QUOTATION MARK020089   F0 A0 82 89    𠂉      Unknown character in range CJK Unified Ideographs Extension B000020   20                     SPACE00000A   0A                     LINE FEED (LF)

There are five ways to write strings in Bash, one of which ($"") is not relevant for this purpose:

  • Literal string with escape characters. There's no way to include a literal newline this way, so that's out. Example:

    $ foo=bar$ bazNo 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
  • Single-quoted string. These can't contain other single quotes, so they're out.
  • Double-quoted string. You can put anything in these, but you have to escape some characters if you want their literal representation - Simply preceding every character with a backslash is not likely to produce the result you want. Also, complicated characters like BELL will have to be included as a literal, making it effectively invisible to the person reading the script or output.
  • ANSI-C Quoting, shown above. This can also contain any character, but you can escape special characters to make the string more readable.

Of the two methods, it's pretty clear that if you want to print any filename you should use ANSI-C Quoting if you don't know what the string might contain. But if you want to always use the "minimal" escaping, you can print the value using printf %q - Compare:

$ printf %q $'word'word$ printf %q $'space separated'space\ separated$ printf %q $'newline\nembedded'$'newline\nembedded'


Not quite what you asked, but might be the best solution given the added reason: python's pipes module has a function called quote, which you can import and which quotes pathnames for shell commands:

$ 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\'"\'"\'\''>>>