3

Q: How do I determine if a string is a valid file name (i.e., uses only valid characters)?

The variable file-name-invalid-regexp was the only thing I could find (docstring: "Regexp recognizing file names which aren’t allowed by the filesystem.") However, the value it gives on my machine (linux) is [^@] (the special character, not the literal "^@").

  • Are you asking about validating entire paths or just filenames without directories? – DoMiNeLa10 Aug 16 '17 at 9:15
  • @DoMiNeLa10: for my narrow purposes, just filenames without directories. It would probably help other users in the future if an answer mentioned validating entire paths, though. – Dan Aug 16 '17 at 9:21
  • If only check file name, I would touch empty file with that name to a temp directory and check success or not. – Enze Chi Aug 16 '17 at 10:58
  • It's not because a string is a valid filename that it's a good idea to use it as a filename. I personally avoid characters which are special to my shell, this includes newline, *, ?, !, &, various kind of brackets, pipe char, <, >, semicolon and maybe a few others. You should also avoid as @ if these filenames are going to be seen on the internet. In fact it might be safe to allow only some "obviously safe" characters (letters, digits, hyphens, dot) and add to that list if/when necessary. – YoungFrog Aug 16 '17 at 12:06
4

However, the value it gives on my machine (linux) is [^@] (the special character, not the literal "^@").

Which is correct.

You would use it by searching the potential filename for that regexp. If a match is found (i.e. on your system, if a null character was found), then it is not a valid filename. e.g.:

(string-match file-name-invalid-regexp fname)

/ is also special of course, and can only be a directory separator, so using this regexp allows file paths which include directory components.

  • 1
    Huh: it turns out that a lot of characters I thought were illegal in filenames (*, ", etc.) are not, in fact, illegal. – Dan Aug 16 '17 at 10:19
  • Indeed. There is a substantial difference between sensible (or portable) filenames, and valid filenames. It's certainly not the best idea to put newlines in filenames, for instance, but that doesn't mean you can't do it. Enforcing sensible filenames is pretty much down to your own judgement, though. – phils Aug 16 '17 at 22:59
  • Tangentially, this is why it's a good habit to use find ... -print0 whenever you'll be processing the output with something that can recognise the null char (e.g. xargs -0). – phils Aug 16 '17 at 23:10
3

In general, you can't. The validity of a file name depends on the filesystem. A file name may be valid in one directory but not in another. There's no way to find out for sure without trying: on a network filesystem, the validity of the name may be enforced by the server without the client knowing the rules.

file-name-invalid-regexp allows you to filter out some invalid file names, which the operating system doesn't support at all. The value of file-name-invalid-regexp just says “null bytes are not allowed” (the special character that's shown as a colored ^@ is a null byte). I think that null bytes are forbidden in file names on all the platforms that Emacs supports.

On most Unix-like operating systems, including Linux and macOS, every character other than a null byte is valid; a slash / cannot appear in a filename component but file-name-invalid-regexp is about the whole path. Most Unix-like operating systems also have a maximum file name length: 255. Additional constraints may apply, for example when accessing a Windows filesystem.

On Windows, several ASCII characters are forbidden in file names (unlike Unix, Windows doesn't allow the special characters of its standard shell in file names). In addition, several base names are forbidden (regardless of the extension). And Windows has a maximum length as well. At least in the official 25.2 Windows binary, file-name-invalid-regexp only reflects the forbidden characters.

Note that if you use Tramp to access files remotely, the file names are processed by Tramp, they bypass the local operating system completely, so file-name-invalid-regexp doesn't apply. This is another reason why file-name-invalid-regexp is pretty much useless.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.