When I use copy *.txt somefolder\ the system seems to copy all *.txt~ files too, which is not what I want. A similar same effect can be seen with dir:

C:\Users\Paul\Documents\Programs\Proffy>dir *.txt
 Volume in drive C is Vista
 Volume Serial Number is EC23-AD6B

 Directory of C:\Users\Paul\Documents\Programs\Proffy

29/11/2008  13:54            35,821 COPYING.txt
31/10/2009  21:54             1,644 INSTRUCTIONS.txt
06/06/2009  15:57             1,393 INSTRUCTIONS.txt~
04/01/2009  11:59               116 Notes.txt
19/04/2009  16:53               134 README.txt
04/01/2009  12:42               132 README.txt~
31/10/2009  21:30               197 TODO.txt
31/10/2009  19:10               414 TODO.txt~
               8 File(s)         39,851 bytes
               0 Dir(s)  41,938,862,080 bytes free

C:\Users\Paul\Documents\Programs\Proffy>

How can I get dir and copy to only operate on files that end with .txt and not .txt~?

link|improve this question

78% accept rate
1  
When I first saw this question, I thought 'yes, that's useful and clear' so I upvoted it. Then I started adding an answer which was coming to the conclusion 'they're treated as special to remind you to rename or delete them'. While I was editing, someone downvoted me, with no comment to explain why. This leaves a nasty taste in my mouth, but I got the message 'help not wanted'. – pavium Oct 31 '09 at 22:37
feedback

migrated from stackoverflow.com Oct 31 '09 at 22:05

This question came from our site for professional and enthusiast programmers.

6 Answers

Apparently the shell considers both the short and the long name for wildcard expansion. Longer explanation can be found in shf301's answer. This is unfortunate and probably a left-over from Ye Olde Days of DOS because that's what cmd is trying to be compatible with—sort of—after all.

Several options here:

  1. Use forfiles, which has a different semantic for wildcard expansion:

    forfiles /m *.txt /c "cmd /c copy @file foo"
    

    This is available at least on Vista and later.

  2. Use for and check the extension:

    for %a in (*.txt) do @if %~xa==.txt @copy "%i" foo
    

    Unfortunately for also returns any files with the .txt~ extension when only using wildcard expansion. That's why we need to check the extension a second time.

  3. Use xcopy. While xcopy has the same semantics for wildcard expansion as the shell you can give it a file with names to ignore:

    echo .txt~>tmpfile
    xcopy *.txt foo /exclude:tmpfile
    del tmpfile
    
  4. Use robocopy. While robocopy has the same semantics for wildcard expansion as the shell you can give it a list of files/wildcards to ignore:

    robocopy . foo *.txt /XF *.txt~
    
  5. Use for, dir and findstr in an appropriate combination. This essentially just filters out all lines that have a ~ at the end and operates on the rest. The if variant above was more elegant, I think.

    for /f "usebackq delims=" %i in (`dir /b *.txt ^| findstr /r "[^~]$"`) do @copy "%i" foo
    
  6. Just for completeness: PowerShell:

    Copy-Item *.txt foo
    
link|improve this answer
feedback

I'm not sure how to stop dir/copy from matching only *.txt but I can explain why *.txt returns what it does; it matches the short file name which ends with .txt for all the files, do a dir /x *.txt to see this. This problem occurs for every set of extensions that start with the same first three characters (e.g. *.htm will match htm, html, and even htmlasdfasdf).

Also most every Windows application will act this way because the API the OS provides to search for files FindFirstFile matches the long file names and short files names. To quote:

The search includes the long and short file names.

You'll have to do some sort of custom filtering as Johannes Rössel answer suggested.

link|improve this answer
feedback
up vote 1 down vote accepted

My solution was to execute del *.xyz~ prior to my copy *.xyz. Not brilliant, but it works.

link|improve this answer
+1. D'oh! Doing things in the right order trumps knowing all the cool commands others offered. – beggs Nov 1 '09 at 15:50
Well, initially I don't assume people would be willing to throw away files :-) – Joey Nov 1 '09 at 21:54
This is not a proper answer to your own question, sorry. Brute force file deletion is NOT a solution. – Breakthrough Feb 22 '11 at 17:46
feedback

Since Joey mentioned completeness, I note, as mentioned here, that this varies according to what command interpreter's DIR and COPY commands one uses. The DIR command in Take Command and its COPY command, for examples, only match long names by default and so don't exhibit this behaviour. (Matching of short as well as long names can be turned on for compatibility with CMD's DIR and COPY commands.)

link|improve this answer
feedback

you could try: copy "*.txt"

link|improve this answer
That's exactly the same as without the quotes. So what should this accomplish? – Joey Nov 1 '09 at 0:56
It seems like it would disinclude the '~' suffix. Hence me using the phrase "could try." – nrhine1 Nov 2 '09 at 4:39
feedback

I doubt you can. Use a more sophisticated program than copy.

link|improve this answer
It's just a little more typing, but you can. – Joey Nov 1 '09 at 1:22
Well, not really, no. Every example you posted is using a different program due to copy's limitations, as I said. – Lee B Nov 1 '09 at 12:20
feedback

Your Answer

 
or
required, but never shown

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