Как скопировать структуру каталогов, но включить только определенные файлы (с использованием пакетных файлов Windows)

103

Как сказано в заголовке, как я могу рекурсивно скопировать структуру каталогов, но включить только некоторые файлы. Например, учитывая следующую структуру каталогов:

folder1
  folder2
    folder3
      data.zip
      info.txt
      abc.xyz
    folder4
    folder5
      data.zip
      somefile.exe
      someotherfile.dll

Файлы data.zip и info.txt могут появляться везде в структуре каталогов. Как я могу скопировать всю структуру каталогов, но включить только файлы с именами data.zip и info.txt (все остальные файлы следует игнорировать)?

Результирующая структура каталогов должна выглядеть так:

copy_of_folder1
  folder2
    folder3
      data.zip
      info.txt
    folder4
    folder5
      data.zip
M4N
источник

Ответы:

169

Вы не упоминаете, должен ли он быть только пакетным, но если вы можете использовать ROBOCOPY, попробуйте следующее:

ROBOCOPY C:\Source C:\Destination data.zip info.txt /E

РЕДАКТИРОВАТЬ: изменен /Sпараметр, /Eчтобы включить пустые папки.

афория
источник
Могу ли я скопировать * .zip с этим синтаксисом? Я пробовал просто писать * .zip вместо data.zip, но он копировал не файлы, а только папки. Я тоже пробовал? .Zip
Нильс Бринч
@ Нильс Бринч: Да, у тебя должно получиться так. Какую именно командную строку вы используете?
афория
1
ROBOCOPY C: \ Source C: \ Destination * .zip / E
Нильс Бринч
Странно. Какую ОС вы используете? У вас есть необходимые разрешения для файлов / папок? Я только что тестировал Win 7 и *.zipработал у меня.
афория
В самом деле!? Я также использую Win 7. Когда я пытаюсь, он просто не копирует файлы. Только папки. Я попробую еще раз. (пока мы находимся на этом, какой синтаксис должен включать больше, чем * .zip - скажем, * .zip и * .jpg.
Нильс Бринч,
29

Альтернативное решение, которое копирует по одному файлу за раз и не требует ROBOCOPY:

@echo off
setlocal enabledelayedexpansion

set "SOURCE_DIR=C:\Source"
set "DEST_DIR=C:\Destination"
set FILENAMES_TO_COPY=data.zip info.txt

for /R "%SOURCE_DIR%" %%F IN (%FILENAMES_TO_COPY%) do (
    if exist "%%F" (
        set FILE_DIR=%%~dpF
        set FILE_INTERMEDIATE_DIR=!FILE_DIR:%SOURCE_DIR%=!
        xcopy /E /I /Y "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
    )
)

Внешний оператор for генерирует любую возможную комбинацию путей подкаталога в SOURCE_DIRи имени в FILENAMES_TO_COPY. Для каждого существующего файла вызывается xcopy. FILE_INTERMEDIATE_DIRсодержит путь к подкаталогу файла, в SOURCE_DIRкотором необходимо создать DEST_DIR.

сакра
источник
1
Мне нужно было скопировать все фотографии из папок и подпапок, этот пакетный скрипт помог. Просто изменил строку set FILENAMES_TO_COPY=data.zip info.txtвыше наset FILENAMES_TO_COPY=*.jpg
Кай Ноак
Я получаю сообщение об ошибке, потому что в пути к файлу есть пробелы (SOURCE_DIR = "C: \ Origin Test", DEST_DIR = "C: \ Dest Test", ошибка: Test "" в этот момент была неожиданной). Я пытался изменить% var% на! Var! везде, но безуспешно. Есть какие-нибудь подсказки о том, как это решить? Вся структура заполнена именами папок с пробелами.
ricardo.scholz
1
Попробуй set "SOURCE_DIR=C:\Origin Test"и set "DEST_DIR=C:\Dest Test". Обратите внимание на размещение двойных кавычек.
sakra
13

попробуйте передать вывод find (то есть путь к файлу) в cpio

find . -type f -name '*.jpg' | cpio -p -d -v targetdir/

cpio проверяет метку времени в целевых файлах - так что это безопасно и быстро.

remove -v для более быстрой операции, как только вы к ней привыкнете.

Гейб Рэйнбоу
источник
2
@Christian, он зависит от cpio, который не является частью стандартной установки.
Crashworks
8

Если Powershell - вариант, вы можете сделать это:

Copy-Item c:\sourcePath d:\destinationPath -filter data.zip -recurse

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

Нил
источник
Повторный запуск изменит пункт назначения. (Он помещает файлы в подпапку.) Это глупое поведение, если вы спросите меня. Вам нужно будет запустить rm -r -ErrorAction:SilentlyContinue d:\destinationPathперед копированием, чтобы исправить это.
MakotoE
7

Спасибо за предыдущие ответы. :)

Этот сценарий называется «r4k4copy.cmd»:

@echo off
for %%p in (SOURCE_DIR DEST_DIR FILENAMES_TO_COPY) do set %%p=
cls
echo :: Copy Files Including Folder Tree
echo :: http://stackoverflow.com
rem     /questions/472692/how-to-copy
rem     -a-directory-structure-but-only
rem     -include-certain-files-using-windows
echo :: ReScripted by r4k4
echo.
if "%1"=="" goto :NoParam
if "%2"=="" goto :NoParam
if "%3"=="" goto :NoParam
setlocal enabledelayedexpansion
set SOURCE_DIR=%1
set DEST_DIR=%2
set FILENAMES_TO_COPY=%3
for /R "%SOURCE_DIR%" %%F IN (%FILENAMES_TO_COPY%) do (
if exist "%%F" (
set FILE_DIR=%%~dpF
set FILE_INTERMEDIATE_DIR=!FILE_DIR:%SOURCE_DIR%=!
xcopy /E /I /Y "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
)
)
goto :eof
:NoParam
echo.
echo Syntax: %0 [Source_DIR] [Dest_DIR] [FileName]
echo Eg.   : %0 D:\Root E:\Root\Lev1\Lev2\Lev3 *.JPG
echo Means : Copy *.JPG from D:\Root to E:\Root\Lev1\Lev2\Lev3

Он принимает переменные «Источник», «Назначение» и «Имя файла». Он также может копировать только файлы указанного типа или отдельные имена файлов.

Любые улучшения приветствуются. :)

Рак Кар
источник
5

Только с find и cp:

mkdir /tmp/targetdir
cd sourcedir
find . -type f -name '*.zip' -exec cp -p --parents {} /tmp/targetdir ";"
find . -type f -name '*.txt' -exec cp -p --parents {} /tmp/targetdir ";"
Роп
источник
4

Подобно решению Паулиуса, но файлы, которые вам не нужны, не копируются, а затем удаляются:

@echo OFF

:: Replace c:\temp with the directory where folder1 resides.
cd c:\temp

:: You can make this more generic by passing in args for the source and destination folders.
for /f "usebackq" %%I in (`dir /b /s /a:-d folder1`) do @echo %%~nxI | find /V "data.zip" | find /v "info.txt" >> exclude_list.txt
xcopy folder1 copy_of_folder1 /EXCLUDE:exclude_list.txt /E /I
Патрик Кафф
источник
4

Чтобы скопировать все текстовые файлы в G: и сохранить структуру каталогов:

xcopy *.txt /s G:
Осберт Снадж
источник
может ли это работать рекурсивно, например, копировать все .txt из подпапок и сохранять структуру каталогов относительно базового каталога?
Micka
3

Это всего лишь две простые команды, но я бы не рекомендовал это, если только файлы, которые вам НЕ нужно копировать, маленькие. Это потому, что это скопирует ВСЕ файлы, а затем удалит файлы, которые не нужны в копии.

xcopy /E /I folder1 copy_of_folder1
for /F "tokens=1 delims=" %i in ('dir /B /S /A:-D copy_of_files ^| find /V "info.txt" ^| find /V "data.zip"') do del /Q "%i"

Конечно, вторая команда довольно длинная, но она работает!

Кроме того, этот подход не требует загрузки и установки каких-либо сторонних инструментов (в Windows 2000+ BATCH для этого достаточно команд).

Паулюс
источник
Большое спасибо. Как вы упомянули, это не идеально, потому что (в моем случае) файлы, которые необходимо скопировать, обычно небольшие, в то время как файлы, которые не следует копировать, больше (и их может быть много).
M4N
2

В Linux и других системах UNIX tarэто легко сделать с помощью команды.

$ tar cvf /tmp/full-structure.tar *data.zip *info.txt

Затем вы идете к цели и:

$ tar xvf /tmp/full-structure.tar 

Конечно, вы можете направить вывод из первого tar во второй, но увидеть, как он работает поэтапно, легче понять и объяснить. Мне не хватает необходимого cd / to / new / path / в следующей команде - я просто не помню, как это сделать сейчас. Надеюсь, кто-нибудь еще сможет это добавить.

$ tar cvf -  *data.zip *info.txt |  tar xvf - 

Tar (gnutar) также доступен в Windows, но я, вероятно, сам использовал бы этот xcopyметод на этой платформе.

JohnP
источник
tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt работал у меня
ssinganamalla
Оба "tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt" и "tar cvf /tmp/full-structure.tar * data.zip * info.txt" дали мне 3 ошибки : (1) «tar: * data.zip: Cannot stat: Нет такого файла или каталога», (2) «tar * info.txt: Невозможно stat: Нет такого файла или каталога», (3) «tar: Выход с статус отказа из-за предыдущих ошибок ». Из какой папки я все это делаю? Я не понимаю этого метода.
user1271772 05
В вопросе написано WINDOWS
Anfelipe
Win10 имеет WSL, поэтому это действительно так. tar доступен в Windows более 20 лет, а использование канала работает еще со времен MS-DOS. В любой среде оболочки важен PWD. PWD - настоящий рабочий каталог. Я признаю, что это решение меньше для конечных пользователей и больше для опытных пользователей или программистов.
JohnP
1
XCOPY /S folder1\data.zip copy_of_folder1  
XCOPY /S folder1\info.txt copy_of_folder1

РЕДАКТИРОВАТЬ: если вы хотите сохранить пустые папки (которые, похоже, при повторном прочтении вашего сообщения) используйте / E вместо / S.

gkrogers
источник
1
он не сохраняет структуру папок.
Paulius
Параметр / E сохраняет структуру папок, включая создание пустых папок при необходимости. Имя файла также работает с подстановочным знаком (например, folder1 \ *. Zip). Я получаю сообщение об ошибке «Файл не найден» только тогда, когда передаю ему полное имя файла, которого не существует (в этом случае я получаю «Файл не найден - xxx.xxx 0 Файл (ы) скопирован»). Когда я задаю ему шаблон который не возвращает файлы (например, folder1 \ *. zzz), я просто получаю «0 файлов (*) скопировано».
gkrogers
1

Используя интерфейс командной строки WinRAR, вы можете скопировать имена файлов и / или типы файлов в архив. Затем вы можете извлечь этот архив в любое удобное для вас место. Это сохраняет исходную файловую структуру.

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

Я использовал:

   rar a -r C:\Downloads\music.rar X:\music\Folder.jpg
  • C: \ Downloads \ music.rar = Архив для создания
  • X: \ music \ = Папка с музыкальными файлами
  • Folder.jpg = Имя файла, которое я хотел скопировать

В результате был создан архив со всеми файлами Folder.jpg в соответствующих подкаталогах.

Этот метод также можно использовать для копирования типов файлов. Если бы все файлы имели разные имена, вы могли бы извлечь все файлы в один каталог. Дополнительные параметры командной строки позволяют архивировать файлы нескольких типов.

Дополнительная информация по этой очень полезной ссылке http://cects.com/using-the-winrar-command-line-tools-in-windows/

Jim_Joat
источник
1

Для тех, кто использует Altap Salamander (двухпанельный файловый менеджер): в параметрах всплывающего окна «Копировать» просто укажите имена файлов или маски. Легко.

Хьюго П
источник
0

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

  1. Создайте список исходных файлов с полными путями, включая букву диска, если она не указана, в текстовом файле.
  2. Включите регулярные выражения в текстовом редакторе.
  3. Добавьте двойные кавычки вокруг каждой строки в случае пробелов - строка поиска (.*)заменит строку "\1"и нажмите заменить все
  4. Создайте две строки для каждого файла - одну для создания каталога, одну для копирования файла (qqq будет заменен на путь назначения) - строка поиска (.*)замените строку md qqq\1\nxcopy \1 qqq\1\nи нажмите заменить все
  5. Удалить имя файла из путей назначения - поиск \\([^\\^"]+)"\nзаменить\\"\n
  6. Заменить в пути назначения (в этом примере A:\srcи B:\dest). Отключите регулярные выражения, выполните поиск по qqq"A:\src\замене B:\dest\и щелкните заменить все.

md создаст вложенные каталоги. copy, вероятно, будет вести себя идентично xcopy в этом примере. Возможно, вы захотите добавить / Y в xcopy, чтобы подавить подтверждение перезаписи. В результате вы получите такой командный файл:

md "B:\dest\a\b\c\"
xcopy "C:\src\a\b\c\e.xyz" "B:\dest\a\b\c\e.xyz"

повторяется для каждого файла в исходном списке. Проверено на Win7.

Крис
источник
-1

Чтобы сделать это с помощью перетаскивания, используйте winzip, есть опция сохранения структуры каталога. Просто создайте новый .zip на уровне каталога, который будет вашим корнем, и перетащите туда файлы.

Гной Дав
источник
Спасибо, но я искал решение для использования из файлов сценариев (пакетных). Итак, без перетаскивания ...
M4N