다음을 통해 공유


The difference in wildcard expansion between Windows and unix/Macintosh

This one took a little getting used to when switching from the Macintosh to Windows. On unix (including Mac OS X shells) wildcard expansion is done by the shell, and then the expanded list of files is passed on to the program being run. On Windows, the shell doesn't do any expansion, and it's up to programs to do expansion.

The advantage of the unix approach is that programs don't have to do any work to support expansion, and the experience is consistent across all programs. As an example, notepad on Windows doesn't seem to support wildcard expansion. So, if you are in a directory with a file called foo.txt and type notepad *.txt, it will launch notepad and tell you "The filename, directory name, or volume label syntax is incorrect." On the Mac, textedit *.txt would open the file right up.

The disadvantage of the unix approach is that it doesn't let you do something like "rename *.txt *.text". On Windows, this command would rename all files ending with .txt to end with .text. If you were to try to write a similar utility for unix, you'd find that when you tried to run it, you'd just get a list of the .txt files as the input arguments, and you wouldn't get any information about the "*.text". That's because the "*.txt" expands to all the .txt files and "*.text" expands to nothing.

It's one of the many differences I found between Mac and Windows where one isn't really better than the other, they are just different and it takes some getting used to. I'm sure there are some of you out there that are religious about this issue and think that one way or the other is clearly superior.

Comments

  • Anonymous
    May 14, 2005
    That's an interesting observation. How does Unix-like OSes handle the rename case?
  • Anonymous
    May 14, 2005
    I would guess that in monad you can override default stuff like possible * expansion (if it even has such).. So for the rename program code you'd make it a bit different maybe..

    Though I am sure monad has better ways thought for this..
  • Anonymous
    May 14, 2005
    In Unix, you need a for loop. using csh:
    csh -f
    foreach file (*.txt)
    mv $file $file:r.text
    end
    exit

    This is impossible to achieve for a novice user, while the Windows equivalnet is short and easy to understand.
  • Anonymous
    May 14, 2005
    The comment has been removed
  • Anonymous
    May 14, 2005
    I don't understand why the shell should expand the wildcards. The application should receive the same arguments entered by the user. And the expansion could be done by a function from a library at the application's will.
  • Anonymous
    May 14, 2005
    Another 'icky' thing in unix is the fact that you can pass commandline parameters using files. eg, in a directory with the file '-rf', running rm * would suddenly delete subdirectories as well.
  • Anonymous
    May 14, 2005
    In linux (and some unix), you may do that with "rename" comamnd:

    rename 's/.txt$/.text/' *.txt

    not as hard as you think. =)
  • Anonymous
    May 15, 2005
    The comment has been removed
  • Anonymous
    May 15, 2005
    Another problem is the difference in capital letters.

    On windows these two files are the same:
    test.txt
    Test.txt

    In the Unix world, its two different files.
  • Anonymous
    May 17, 2005
    The comment has been removed
  • Anonymous
    May 18, 2005
    On Linux, using the rename command, do

    rename 's/txt$/text/' .txt
    or
    rename 's/.txt$/.text/'

    A little bit more verbose than the Windows command. Of course, if really missing one could write a tool that matches more closely your Windows CLI. You could end up with something like:

    rename2 "
    .txt" "
    .text"
  • Anonymous
    May 18, 2005
    The comment has been removed
  • Anonymous
    May 18, 2005
    Of course, the Windows shell puts the burden of implementing wildcards on the developer...and you never really know as a user what each command will do with wildcards.

    Not being religious, just sayin' is all. :)
  • Anonymous
    May 18, 2005
    The comment has been removed
  • Anonymous
    May 18, 2005
    The comment has been removed
  • Anonymous
    May 18, 2005
    In response to jminstall; heh - I'm quite certain that, in general, most novice users don't even know of the sheer existence of the command prompt, let alone the commands therein. I've encountered MSCEs who don't even know what it is. Sometimes I wonder what will happen if the command prompt really does go away.
  • Anonymous
    May 18, 2005
    In Linux:
    % rename .txt .text *.txt

    Maybe you should try to patent this too?
  • Anonymous
    May 18, 2005
    Interestingly enough, unix works properly if there are NO .text files - for example

    $ ls .fred
    .fred: No such file or directory

    Of course, if there are some, the hypothetical rename won't work. You could always quote the * as appropriate however, which would be okay, although not quite as obvious as the user would think.
  • Anonymous
    May 18, 2005
    The comment has been removed
  • Anonymous
    May 18, 2005
    The comment has been removed
  • Anonymous
    May 18, 2005
    Actually, in Linux we get the best of both worlds. The command "rename" can be used to do exactly that. It would look something like this:
    <br /><br />
    rename .txt .text *.txt<br />
    <br />
    This would use the nice expansion features of *nix to get all of the ".txt" files via the *.txt command and then run a regex against them (something Win still lacks as far as I am aware of) to convert all instances of ".txt" in their names to ".text".<br />All of this transparent to the user...no need to do any shell scripting.<br />
    I have used all three systems, Mac the least, and both Win and *nix as desktops and as servers. In my opinion the slogan for *nix should be "Any thing you can do I can do better."
  • Anonymous
    May 18, 2005
    On Linux, using the rename command, do

    rename 's/txt$/text/' .txt
    or
    rename 's/.txt$/.text/'

    A little bit more verbose than the Windows command. Of course, if really missing one could write a tool that matches more closely your Windows CLI. You could end up with something like:

    rename2 "
    .txt" "
    .text"
  • Anonymous
    May 18, 2005
    On Linux (at least on a RH 8) I've found a command called "rename". The meaning of the parameters slightly differs from the Windows one (as explained in the man page). The equivalent for your example will be:

    rename .txt .text *.txt

    However I haven't found it on a SunOS, so seems that in some systems you still have to deal with mv and scripts.

    In other news, some comands (i.e. find) avoid wildcard shell expansion by escaping it: *. Maybe that's the solution if you want an exact unix clone of Windows rename.
  • Anonymous
    May 18, 2005
    The comment has been removed
  • Anonymous
    May 18, 2005
    This ugliness been in W$ since DOS 1.0.
    does W$ guarantee atomicity?
    what if i have file called '*.txt'?
    why can't I "ren **.txt **.text" ?
  • Anonymous
    May 19, 2005
    Greetings,
    Retrying, as the MSDN blogs was dying on comments before.

    Actually, you're not quite right about the '*.txt *.text' problem. The best way to explore shell expansion is to use 'echo'. For example, in a directory with a few .txt files and no .text files, try:

    echo .txt .text

    and you'll see the list of .txt files, followed by '
    .text'. See, shell expansion is 'smart'. If there is no file expansion result, it reverts to the original text provided.

    So you could write a tool which, if given a wildcard that matched nothing at the end, figured out that '
    .text' was the destination name, and did all the right things. The problem with that would come when you have:

    1.txt 2.txt 3.txt 4.text

    and wanted to renamed *.txt to *.text. That's where it breaks down, and so instead you have the shell programming power (which Windows simply doesn't touch):

    for i in *.txt; do mv $i basename $i .txt.text; done

    See, that's pretty powerful, but it takes a while to learn it, and it's too complex for most users. This is far more valuable in places where you want to manipulate the filename in more complex ways (conditional behavior, for instance) than just changing the extension, but DOS (and the Windows shell, by extension) makes the common task easy at the expense of making the complex task impossible. Once upon a time that was a criticism of MacOS as well, but now at least the complex is possible.

    Anyhow, good luck with the transition, I went the other way, to OSX as the best UI atop Unix out there, and am quite happy.

    Oh, and nill illigitimi carborundum.

    -- Morgan Schweers