Как я могу получить команды "dir" и "copy" для работы с "* .xyz", но не с "* .xyz ~"?

1370
pauldoo

Когда я использую copy *.txt somefolder\систему, кажется, копирует все *.txt~файлы тоже, что не то, что я хочу. Подобный же эффект можно увидеть с 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> 

Как я могу получить dirи copyработать только с файлами, которые заканчиваются, .txtа не .txt~?

4
Когда я впервые увидел этот вопрос, я подумал «да, это полезно и понятно», поэтому я проголосовал за него. Затем я начал добавлять ответ, который подходил к выводу «они рассматриваются как особые, чтобы напомнить вам переименовать или удалить их». Пока я редактировал, кто-то отказался от меня, без комментариев, чтобы объяснить почему. Это оставляет неприятный вкус во рту, но я получил сообщение «помощь не требуется». pavium 15 лет назад 1

6 ответов на вопрос

5
Joey

Очевидно, что оболочка учитывает как короткое, так и длинное имя для подстановочного знака. Более подробное объяснение можно найти в ответе shf301 . Это прискорбно и, вероятно, осталось от Ye Olde Days из DOS, потому что это то, что cmdпытается быть совместимым с чем-то вроде.

Несколько вариантов здесь:

  1. Используйте forfiles, у которого есть другая семантика для расширения подстановочного знака:

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

    Это доступно по крайней мере на Vista и позже.

  2. Используйте forи проверьте расширение:

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

    К сожалению, forтакже возвращает любые файлы с .txt~расширением, когда используется только подстановочное расширение. Вот почему нам нужно проверить расширение во второй раз.

  3. Используйте xcopy. Хотя xcopyдля расширения с подстановочными знаками используется та же семантика, что и для оболочки, вы можете дать ему файл с именами, которые следует игнорировать:

    echo .txt~>tmpfile xcopy *.txt foo /exclude:tmpfile del tmpfile 
  4. Используйте robocopy. Хотя robocopyдля расширения подстановочных знаков используется та же семантика, что и для оболочки, вы можете указать список файлов / подстановочных знаков, которые следует игнорировать:

    robocopy . foo *.txt /XF *.txt~ 
  5. Используйте for, dirи findstrв соответствующей комбинации. Это, по сути, просто отфильтровывает все строки, которые имеют ~в конце и работает с остальными. ifВариант выше был более элегантным, я думаю.

    for /f "usebackq delims=" %i in (`dir /b *.txt ^| findstr /r "[^~]$"`) do @copy "%i" foo 
  6. Просто для полноты: PowerShell:

    Copy-Item *.txt foo 
1
shf301

Я не уверен, как остановить dir / copy от сопоставления только * .txt, но я могу объяснить, почему * .txt возвращает то, что он делает; оно соответствует короткому имени файла, которое заканчивается на .txt для всех файлов, выполните команду dir / x * .txt, чтобы увидеть это. Эта проблема возникает для каждого набора расширений, которые начинаются с тех же первых трех символов (например, * .htm будет соответствовать htm, html и даже htmlasdfasdf).

Также почти каждое приложение Windows будет действовать таким образом, потому что API, предоставляемый ОС для поиска файлов, FindFirstFile соответствует длинным именам файлов и коротким именам файлов. Цитировать:

Поиск включает в себя длинные и короткие имена файлов.

Вам придется сделать какую-то специальную фильтрацию, как предложил ответ Йоханнеса Ресселя.

1
pauldoo

Мое решение было выполнить del *.xyz~до моего copy *.xyz. Не блестяще, но это работает.

+1. D'о! Делать вещи в правильном порядке козыри, зная все классные команды, предложенные другими. beggs 15 лет назад 0
Ну, изначально я не предполагаю, что люди захотят выбросить файлы :-) Joey 15 лет назад 0
Это не правильный ответ на ваш собственный вопрос, извините. Удаление файлов методом грубой силы НЕ является решением проблемы. Breakthrough 13 лет назад 0
0
JdeBP

Поскольку Джо упомянул полноту, я отмечаю, как упомянуто здесь, что это варьируется в зависимости от того, что команды переводчицы DIRи COPYкоманды одного использования. Команда DIRв Take Command и ее COPYкоманда, например, по умолчанию соответствуют только длинным именам и поэтому не демонстрируют такого поведения. ( Соответствие как коротких, так и длинных имен может быть включено для совместимости с CMD DIRи COPYкомандами.)

0
Dennis

Существующий ответ покрывал, копируя файлы, только упал, но не перечисляя их.

Вы можете использовать бит архива для обеих целей. Хотя он предназначен для использования с XCOPY 1, он также работает с DIR 2 .

шаги:

  1. Убедитесь, что бит архива установлен для всех .txtфайлов:

    ATTRIB +A *.txt 
  2. Удалить бит архива из всех .txt~файлов:

    ATTRIB +A *.txt~ 
  3. Список всех .txtфайлов, для которых установлен бит архивирования:

    DIR /AA *.txt 

    или скопируйте их в somefolder:

    XCOPY /A *.txt somefolder/ 

1 XCOPY использует /Aпереключатель, чтобы исключить все файлы, для которых не установлен их архивный бит. Это может быть использовано для исключения определенных файлов (например, временных файлов) из ежедневных резервных копий. С помощью /Mпереключателя он также удаляет архивный бит из файлов, что удобно при копировании файлов на небольшие устройства хранения (например, на дискеты). Кроме того, изменение файлов автоматически устанавливает бит архива, поэтому /Mпереключатель можно использовать для инкрементного резервного копирования.

2 DIR /AA показывает только те файлы, для которых установлен атрибут архива.

-1
eqzx

Вы можете попробовать: скопировать "* .txt"

Это точно так же, как без кавычек. Так, что это должно достигнуть? Joey 15 лет назад 0
Похоже, это не включает суффикс '~'. Поэтому я использовал фразу «мог бы попробовать». eqzx 15 лет назад 0