Копировать / перемещать файлы определенных типов из подпапок в общую папку

1031
WraythOsu

Ситуация:

Многочисленные подпапки со случайными именами папок, содержащие несколько файлов со случайными именами. Одни я хочу сохранить, другие можно удалить.

Цель:

Переместите файлы с расширениями: * .exe * .pdf * .avi или другими указанными расширениями из подпапок в общую отдельную папку, не создавая прежнюю структуру папок. Так что у меня есть одна папка с только файлами, которые я хочу, оставляя позади любые другие типы файлов. Затем запишите имена каталогов подпапок (results-log.log) и удалите подпапки и все, что в них осталось.

Пример; отправной:

  • Parent1
    • sub1
      • random1.exe
      • random2.pdf
      • random3.txt
    • sub2
      • random4.exe
      • random5.avi
      • random6.log
      • random7.jpg

Конечный результат:

  • parent2
    • Результаты-log.log
    • random1.exe
    • random2.pdf
    • random4.exe
    • random5.avi

Поэтому я искал другие ответы, и похоже, что мне нужен какой-то цикл FOR, но я недостаточно понимаю, как это работает с параметрами, чтобы делать то, что мне нужно. Перемещение pdf-файлов в родительскую папку из подпапки с именами переменных - это один из примеров, на который я посмотрел, и просмотрел предлагаемое чтение, но я совершенно не понимаю, как работают параметры и переменные. Особенно там, где мне нужно охватить несколько типов файлов.

Пока я смотрю на что-то вроде этого:

@ECHO OFF SETLOCAL EnableExtensions set "_parent=c:\logs\cache\" set "_dest=c:\archive\" for /D /r %%G in ("%_parent%\*") do ( if exist "%%~G\*.pdf" ( echo move /B "%%~G\*.pdf" "%_dest%\" ) else ( echo nothing to copy "%%~G\*.pdf" "%_parent%\" ) ) 
  • Строка 3 Я полагаю, что устанавливает «c: \ logs \ cache \» в качестве родительской папки, так что в моем примере об этом будет равно «parent1»
  • В строке 4 следует указать место назначения, например, для папки «parent2» как «c: \ archive»
  • Строка 5 является %%Gправильным? Имеет ли значение, что это за письмо?
  • Строка 6, как мне указать другие расширения файлов, которые я хочу найти?
  • Строка 7 я хочу использовать moveили что-то еще, и какой /Bпараметр? /yединственный, кого я знаю для move.

Надеюсь, достаточно информации, можете редактировать по мере необходимости для получения дополнительной информации.

2

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

3
mrfreester

Все, что вам нужно сделать, это сделать несколько ifзаявлений, я думаю. Так что внутри вашего цикла это будет выглядеть так:

IF exist "%%G\*.pdf" ( move /Y "%%G\*.pdf" "%_dest%\" echo %%G>>"%_dest%\results-log.log )  IF exist "%%G\*.exe" ( move /Y "%%G\*.exe" "%_dest%\" echo %%G>>"%_dest%\results-log.log ) IF exist "%%G\*.avi" ( move /Y "%%G\*.avi" "%_dest%\" echo %%G>>"%_dest%\results-log.log ) 

Если вы хотите, чтобы сообщение не сообщало о перемещении, вы всегда можете установить некоторую переменную, если она попадет внутрь одного из этих IFоператоров, и проверить, установлено ли оно.

Я не уверен /B, что, это не выглядит правильным для меня. Я думаю, что вы правы /y.

GМожет быть любой символ, но он не может быть больше, чем один символ. Gэто то, что обычно используется.

Я бы посоветовал изучить скрипты powershell для таких вещей. На мой взгляд, проще и проще делать такие вещи с меньшим количеством строк кода. Может быть команда для перемещения всех файлов с несколькими расширениями одновременно, но из того, что я понимаю, синтаксис обычно не доступен для перемещения в большинстве версий DOS.

РЕДАКТИРОВАТЬ:

Я проверил это локально, и это похоже на то, что вы делаете. Вам нужно будет настроить его для вашего конкретного случая.

@ECHO OFF SETLOCAL EnableExtensions enabledelayedexpansion set _parent=c:\logs\cache\ set _dest=c:\archive\ set found=0  for /R %_parent% %%G in (.) do ( set found=0 IF exist "%%G\*.pdf" ( move /Y "%%G\*.pdf" "%_dest%\" set found=1 ) IF exist "%%G\*.exe" ( move /Y "%%G\*.exe" "%_dest%\" set found=1 ) IF exist "%%G\*.avi" ( move /Y "%%G\*.avi" "%_dest%\" set found=1 )  IF !found!==1 ( rd /s /q "%%G" echo %%G>>"%_dest%\results-log.log" ) )  endlocal 

Использование /Dопции в forцикле присоединяет текущий каталог, в котором вы запускаете скрипт, к %%Gпеременной, которую я не думаю, что вы хотите. То, как я написал это выше, в основном гласит, что нужно восстановить все папки в родительском каталоге и установить его %%Gв этом месте (.).

Вы должны добавить enabledelayedexpansionтакже, чтобы вы могли использовать foundпеременную в разных блоках, затем вам нужно вызывать !found!вместо того, %found%чтобы использовать ее. Просто странная причуда пакетного скриптинга.

Если весь этот синтаксис кажется вам действительно странным, вы не одиноки. Вам просто нужно провести исследование и просто провести собственное тестирование, чтобы увидеть, что происходит, пока вы не заставите его делать то, что вы хотите. Надеемся, что когда вы перейдете на powershell, вы найдете отладку с использованием powershell ISE, а используемый синтаксис намного проще.

Я не проверял весь этот синтаксис, но он должен по крайней мере приблизить вас к тому, что вам нужно. Я бы поставил все условия в одно выражение if, но я думаю, что вы можете выполнять только условия «и», а не «или» для условий if. Еще одна причина использовать powershell :) mrfreester 9 лет назад 0
Хорошо, чтобы убедиться, что я правильно понимаю. Ваш код заменяет мое выражение `IF`, но я по-прежнему сохраняю первые 4 строки такими, какие они есть, верно? Тогда что мне делать с частью else? Добавить его после всех моих операторов `IF` с` echo` в файл журнала? PS Вместо этого я готов сделать это с PowerShell, но я еще меньше знаю об использовании PS, он находится в моем списке вещей, которые мне нужно изучить в ближайшее время. WraythOsu 9 лет назад 0
Я добавил весь пример использования переменной, чтобы увидеть, было ли что-либо перемещено. Вы будете использовать это вместо оператора else, так как пакет не поддерживает else if mrfreester 9 лет назад 0
Работает!!! (представьте себе молодого Анакина в eps 1) :-) Итак, последнее, что нужно сделать, это удалить старые подпапки после того, как мы переместим файлы. так что мне добавить `rd / s / q %% G` между строкой` move` и строкой `set` в каждом выражении? Единственное, что меня беспокоит, это то, что я не хочу удалять папку, которая может содержать тип файла, который я не учел в сценарии. Допустим, папка отображается как .msi вместо .exe, я хочу, чтобы эта папка оставалась одна пока. Поэтому я хочу, чтобы он удалил папку, только если файл был удален. WraythOsu 9 лет назад 0
Я бы, вероятно, поставил строку `rd / q %% G` последним блоком if, в который вы записываете файл журнала, так как вы должны входить в него, только если вы удалили что-то в предыдущих блоках if. Я бы, вероятно, пропустил параметр `/ s`, так как думаю, что он удалит каталог, даже если в нем еще есть файлы. Если вы пропустите `/ s`, то я почти уверен, что он будет делать то, что вы хотите, то есть удалять папку, только если она пуста. mrfreester 9 лет назад 0
Этот ответ можно запустить после всего цикла for, чтобы удалить все пустые папки. Вам просто нужно заменить каталог, который они указывают, вашей переменной _parent: http://superuser.com/a/39679/352083 mrfreester 9 лет назад 0
спасибо, что остался со мной на этом! Так что на самом деле подкаталоги не будут пустыми, у них все еще будут небольшие файлы, которые меня не волнуют и которые я хочу удалить, поэтому я хочу использовать `/ s`. Но я не хочу удалять все, начиная с _parent и далее. Если появляется новый тип файла, который не перемещается, я хочу, чтобы эта папка осталась на месте, чтобы я мог оценить его. Поэтому я просто хочу удалить папки, из которых я переместил файл. WraythOsu 9 лет назад 0
Хорошо, я вставил `rd / s / q %% G`, и он сделал то, что хотел. Единственная проблема заключалась в том, что он не удалял каталог с пробелом в нем. Так что я могу просто поместить `" "` вокруг `%% G` так:` rd / s / q "%% G" `? Я знаю, что цитаты могут делать странные вещи, если не все сделано правильно. Так что все, что мне сейчас нужно, это правильное форматирование для этой строки, и на это есть ответ. Woohoo! WraythOsu 9 лет назад 0
Понимаю. Существует вероятность, что использование / s может удалить некоторые папки, прежде чем перемещать файлы, в зависимости от того, как цикл проходит по папкам. Например, если у вас есть `f1 / f2` и файлы в них, и цикл сначала проходит через` f1`, если вы удалите эту папку, вы можете случайно удалить все из `f2`. Вы можете добавить несколько эхо-операторов, чтобы увидеть порядок. Если цикл всегда проходит через верхнюю папку, сначала считайте, что вам повезло, и все, что вам нужно сделать, это использовать `rd` в последнем операторе if. Если вам не повезет, вам придется проработать еще немного логики. mrfreester 9 лет назад 0
Хорошо, я понимаю, что вы говорите, я не думаю, что у меня будут подпапки, поэтому я не буду беспокоиться об этом, поэтому просто нужна команда `RD` для обработки имен папок с пробелами, и мы все настроены. WraythOsu 9 лет назад 0
Да, это должно быть все, что вам нужно, просто заключите в кавычки. Если по какой-то причине это не сработает, дайте мне знать. mrfreester 9 лет назад 0
Это сработало, я отредактировал код в вашем ответе и пометил его как ответивший. Большое спасибо за вашу помощь @mrfreester! WraythOsu 9 лет назад 0