vote up 2 vote down star
1

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~?

flag
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 at 22:37

migrated from stackoverflow.com

6 Answers

vote up 2 vote down

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|flag
vote up 1 vote down check

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

link|flag
+1. D'oh! Doing things in the right order trumps knowing all the cool commands others offered. – beggs Nov 1 at 15:50
Well, initially I don't assume people would be willing to throw away files :-) – Johannes Rössel Nov 1 at 21:54
vote up 0 vote down

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|flag
vote up 0 vote down

Don't use windows and Use cp in linux, haha. :-p

link|flag
vote up -1 vote down

you could try: copy "*.txt"

link|flag
That's exactly the same as without the quotes. So what should this accomplish? – Johannes Rössel Nov 1 at 0:56
It seems like it would disinclude the '~' suffix. Hence me using the phrase "could try." – nrhine1 Nov 2 at 4:39
vote up -1 vote down

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

link|flag
It's just a little more typing, but you can. – Johannes Rössel Nov 1 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 at 12:20

Your Answer

Get an OpenID
or
never shown

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