Is there some rule for using \ or /?
For example, both cd c:/ and c:\ works fine. Using mkdir x/y does not work, saying that "syntax is incorrect", but works with mkdir x\y.
Can anyone explain what's the difference?
On Windows the forward slash / is in general for parameters and the backslash \ is the directory separator in file/folder names with absolute or relative paths, see Microsoft documentation Naming Files, Paths, and Namespaces.
The Windows file system kernel functions handle also file/folder paths with / as directory separator by auto-correcting them to \ internally for a better compatibility with Unix/Mac platforms like #include statements in C/C++/C# source code files referencing header files with relative paths using / as directory separator or URLs in HTML files with also using / as separator. That are just two of many examples on where a forward slash is used as separator between strings representing directories on file system.
But a Windows batch file should be written with using only \ as directory separator in file/folder strings.
On Unix/Mac the directory separator is / and - is used for options which is sometimes problematic because of file/folder names can also start with character -.
How argument strings are parsed depends on used compiler and the application/command itself. There are some general rules for each platform, but each programmer of an application can define the argument parsing rules by oneself. So it is always recommended to read the documentation of the application or command to use. On Windows this can be in general done by running the command/application with /? while on Unix/Mac the option to get help is usually -? or -h or --help.
There are many applications ported from Unix to Windows which require parameters being specified on command line with - instead of / like ping.
Related
As in the above title question, my current working directory contains one directory "a" which contains another directory "b". The correct path to directory "b" is "a\b" (on Windows platform). Assuming that "/" is used as "switch" character I expect function GetFileAttributesA() to give an error for the specified path "a/b". The following documentation says nothing about additional internal path separator conversion.
The question is why GetFileAttributesA() works with unix path separators?
The C++ code is (C++14):
#include <windows.h>
int main()
{
DWORD gfa1 = GetFileAttributesA("a\\b");
DWORD gfa2 = GetFileAttributesA("a/b");
// Both gfa1 and gfa2 are equal to FILE_ATTRIBUTE_DIRECTORY
// I expect the gfa2 to be INVALID_FILE_ATTRIBUTES
return 0;
}
The reason why I would expect function to fail with "a/b" is simple. To simplify I have one function which tells if particular path is a directory for both Linux and Windows system. As long as the function has the same behaviour for slashes and backslashes on Windows I'm forced to add the same behaviour on Linux (separator conversion) or vice-versa (do not allow creating directories with "/" on Windows which is not supported by this function).
Many parts of Windows accept both forward and backward slashes, including nearly all the file API's. Both slashes are reserved characters, and can not appear within a file or directory name.
I am not sure this is detailed in a central place, but for the file API's, the Naming Files, Path, and Namespaces document has this to say:
File I/O functions in the Windows API convert "/" to "\" as part of converting the name to an NT-style name, except when using the "\?\" prefix as detailed in the following sections.
As for:
Assuming that "/" is used as "switch" character
Since on the command line any file or directory path containing a space must be quoted, you can safely split such a path with forward slashes from any switches/parameters on that space character or quotation rules. Similar to how there is no issue with - being in file and directory names, but also used by many programs for command line switches.
I already looked through other topics, but I still couldn't find a solution. I'm trying to install "nxhtml" plugin for Emacs in windows 7. I already setup my "HOME" environment variable as "C:\". So, my .emacs.d folder is there, and I put the nxhtml in there and added the following line to my "_emacs.d" file, as the readme says:
(load "C:\.emacs.d\nxhtml\autostart.el")
But it doesn't load.
I also tried putting:
(add-to-list 'load-path "C:\.emacs.d\nxhtml")
(load "autostart.el")
But to no avail... can anyone shed some light here? tnx.
A number of points here:
Firstly, _emacs.d is not a default file name for your init file, ie emacs will not load it automatically. Try ~/.emacs.d/init.el, or ~/.emacs instead.
Secondly, Windows 7 has a feature where it prevents programs from writing to certain system directories, but for backwards compatibility for the many old programs that do this, rather than causing them to fail, it silently redirects the write elsewhere, in an application specific directory. C:\ is one of those directories, so setting your HOME to point there is asking for trouble.
Thirdly, see the other response about backslash being an escape character in Lisp strings.
\ is special in the (double-quote) read syntax for strings, as certain characters take on a new meaning when prefixed by a backslash (e.g. \n is a newline, \t is a tab, and \" is a double-quote character). When the following character does not have any special meaning in conjunction with the backslash, that character is used verbatim, and the backslash is ignored.
"C:\.emacs.d\nxhtml\autostart.el" is actually the string:
C:.emacs.d
xhtml^Gutostart.el
To include a \ in the string you need to write \\
However, although it will understand the backslashes, Emacs is nowadays consistent across all platforms in allowing / as a directory separator1; so just do that instead.
1 and the obsolete directory-sep-char variable has been removed entirely.
Here are many comments on some questions (especially for shell) that say basically one or more of the following:
This will fail on file names that contain spaces, newlines, etc,
This will fail if the file is a symbolic link (or not),
This will fail if the $filaneme is a directory and not regular file,
and so on.
While I understand that every script needs its own testing environment, but
these are some common things for what the script should be immune against.
So, my intention is to write a script what will create some directory hierarchy
with "specially crafted" file names for testing purposes.
The question is: what "special" file names are good for this test?
Currently I have (the script creates files and directories) with:
space in the file name
newline in the file name
file name that starts with one of:
- (like command argument)
# (comment char)
! (command history)
file name that contains one of:
| char (pipe)
() chars
* and ? (wildcards)
file name with unicode characters
all above for the directories
symbolic link to the directory
symbolic link to the file
Any other idea what I shouldn't miss?
What comes to my mind:
quotes in the filename single and double
the $ character at the start
several redirection characters like > < << <<<
the ~ char ($HOME)
the ';' (as command delimiter)
backslash in the filename \
basically, go thru ascii table and test all chars, if you think that you need this :)
Some another comments:
If you want test scripts for the stack-overflow questions, you should create one file with the OP's content (calling as the "basic file")
And the all above "special files" should be symlinks to the above basic file. With this method you can easily modify the content of the files (you need change only one - the basic).
Or, if symlinks not a solution for you use hard-links.
Not directly about special characters in the filenames, but it is good care about:
different case filenames, especially for images like image.jpg image.JPG, same filename only different extension
EDIT: Ideas from the comments:
Very long filenames, lots and lots of files, and very deep directory hierarchies (tripleee)
I am using ActiveState perl with Komodo Edit.
I am getting the following error.
Can't locate MyGengo.pm in #INC (#INC contains: C:/Perl/site/lib C:/Perl/lib .)
at D:\oDesk\MyGengo Integration\sample line 6.
Why is the interpreter looking in C:/Perl/lib instead of C:\Perl\lib?
Doesn’t it know that it is Windows and not Linux?
EDIT
I resolved the problem by copying the .pm file in C:\Perl\lib directory. I think, the issue happened since this module was manually downloaded. PPM install would copy the .pm file to the lib directory.
As far as Windows is concerned, C:/Perl/lib and C:\Perl\lib are the same directory.
The perlport documentation notes (emphasis added)
DOS and Derivatives
Perl has long been ported to Intel-style microcomputers running under systems like PC-DOS, MS-DOS, OS/2, and most Windows platforms you can bring yourself to mention (except for Windows CE, if you count that). Users familiar with COMMAND.COM or CMD.EXE style shells should be aware that each of these file specifications may have subtle differences:
my $filespec0 = "c:/foo/bar/file.txt";
my $filespec1 = "c:\\foo\\bar\\file.txt";
my $filespec2 = 'c:\foo\bar\file.txt';
my $filespec3 = 'c:\\foo\\bar\\file.txt';
System calls accept either / or \ as the path separator. However, many command-line utilities of DOS vintage treat / as the option prefix, so may get confused by filenames containing /. Aside from calling any external programs, / will work just fine, and probably better, as it is more consistent with popular usage, and avoids the problem of remembering what to backwhack and what not to.
Your comment shows that you’re using mygengo-perl-new but have it installed in C:\Perl\lib\MyGengo\mygengo-api\nheinric-mygengo-perl-new-ce194df\mygengo. This is an unusual location to install the module. The way the module is written, it expects mygengo.pm to be in one of the directories named in #INC. Client code then pulls it in with
use mygengo;
My suggestion is to move mygengo.pm from C:\Perl\lib\MyGengo\mygengo-api\nheinric-mygengo-perl-new-ce194df\mygengo to C:\Perl\site\lib.
As an alternative if you are using mygengo as part of another package that you’re developing, you could drop mygengo in your source tree, perhaps as a git submodule. Don’t forget to add use lib 'mygengo'; if you do it this way.
For full details, read about the #INC search process in the perlfunc documentation on require and the extra semantics for modules via use.
General advice on slashes versus backslashes
Even if your code will run on Windows only, prefer using forward-slash as the separator in hardcoded paths. Backslash is an escape character in the Perl language, so you have to think more carefully about it. In double-quoted strings, you have to remember to escape the escape character to get its ordinary meaning, e.g.,
# my $dir = "C:\Perl\lib"; # oops, $path would be 'C:Perlib'
$dir = "C:\\Perl\\lib";
The situation can be a little nicer inside single-quoted strings. Setting $dir as in
$dir = 'C:\Perl\lib';
does what you expect, but say you want $dir to have a trailing slash.
$dir = 'C:\Perl\lib\';
Now you have a syntax error.
Can't find string terminator "'" anywhere before EOF at dirstuff line n.
You may want to interpolate another value into $dir.
$dir = 'C:\Perl\lib\$module'; # nope
Oh yeah, you need double-quotes for interpolation.
$dir = "C:\Perl\lib\$module"; # still not right
After headscratching and debugging
$dir = "C:\\Perl\\lib\\$module"; # finally
Backslash is therefore more mistake-prone and a maintenance irritant. Forward slash is an ordinary character inside both single- and double-quoted strings, so it almost always means what you expect.
As perlport notes, the Windows command shell treats forward slash as introducing options and backslash as path separators. If you cannot avoid the shell, then you may be forced to deal with backslashes.
I need to construct a file path inside a Perl script. Which path separator should I use to allow my script to work on both Windows and Unix?
Keep in mind that Windows needs a drive letter.
You want File::Spec's catpath:
catpath()
Takes volume, directory and file portions and returns an entire path.
Under Unix, $volume is ignored, and directory and file are
concatenated. A '/' is inserted if need be. On other OSes, $volume
is significant.
$full_path = File::Spec->catpath( $volume, $directory, $file );
You want File::Spec. There are specific versions for Unix, Win32, and MacOS as well others.
If you find File::Spec cumbersome, as I do, try Path::Class. It gives you directory and file objects to work with rather than having to call long winded File::Spec class methods on strings.
It sounds like you are using path separator to mean the character between directory/file name components. But just in case you meant the other meaning:
Some things (notably environment variables like MANPATH or PERL5LIB) take a list of file or directory names, separated by a path separator character. Perl's Config module portably supplies such a character as $Config::Config{'path_sep'}.
Q:Which path separator should I use to allow my script to work on both Windows and Unix?
A: /.
Explanation:
Windows can work similarly to Unix with / as path separator.
(Mac OS uses : as a path separator instead of /).
The File::Spec modules can also help.
use File::Spec::Functions;
chdir(updir()); # go up one directory
$file = catfile(curdir(), 'temp', 'file.txt');
# on Unix and Win32, './temp/file.txt'
# on Mac OS, ':temp:file.txt'
# on VMS, '[.temp]file.txt'
Source:
http://www.xav.com/perl/lib/Pod/perlport.html