Comment copier une structure de répertoires mais inclure uniquement certains fichiers (en utilisant des fichiers batch Windows)
-
19-08-2019 - |
Question
Comme le titre le dit, comment puis-je copier récursivement une structure de répertoires en n'incluant que quelques fichiers? E.g étant donné la structure de répertoire suivante:
folder1
folder2
folder3
data.zip
info.txt
abc.xyz
folder4
folder5
data.zip
somefile.exe
someotherfile.dll
Les fichiers data.zip et info.txt peuvent apparaître n'importe où dans la structure de répertoires. Comment copier la structure de répertoires complète, en n'incluant que les fichiers nommés data.zip et info.txt (tous les autres fichiers doivent être ignorés)?
La structure de répertoire obtenue devrait ressembler à ceci:
copy_of_folder1
folder2
folder3
data.zip
info.txt
folder4
folder5
data.zip
La solution
Vous ne mentionnez pas s'il doit s'agir uniquement d'un lot, mais si vous pouvez utiliser ROBOCOPY
, essayez ceci:
ROBOCOPY C:\Source C:\Destination data.zip info.txt /E
EDIT: modification du paramètre / S
en / E
pour inclure les dossiers vides.
Autres conseils
Une solution alternative qui copie un fichier à la fois sans nécessiter 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!"
)
)
L'instruction externe for génère toute combinaison de chemin possible du sous-répertoire dans SOURCE_DIR
et du nom dans FILENAMES_TO_COPY
. Pour chaque fichier existant, xcopy est appelé. FILE_INTERMEDIATE_DIR
contient le chemin du sous-répertoire du fichier dans SOURCE_DIR
, qui doit être créé dans DEST_DIR
.
essayez de diriger la sortie de find (c'est-à-dire le chemin du fichier) dans cpio
find . -type f -name '*.jpg' | cpio -p -d -v targetdir/
cpio vérifie l’horodatage des fichiers cibles - il est donc sûr et rapide.
retirez -v pour un fonctionnement plus rapide, une fois que vous vous y êtes habitué.
Si Powershell est une option, vous pouvez le faire:
Copy-Item c:\sourcePath d:\destinationPath -filter data.zip -recurse
Le principal inconvénient est qu’il copie tous les dossiers, même s’ils sont vides, car aucun fichier ne correspond au filtre que vous spécifiez. Vous pourriez donc vous retrouver avec une arborescence pleine de dossiers vides, en plus des quelques dossiers contenant les fichiers que vous souhaitez.
Merci aux réponses précédentes. :)
Ce script nommé "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
Il accepte les variables "Source", "Destination" et "Nom de fichier". Il ne peut également copier que des types de fichiers spécifiés ou des noms de fichiers sélectifs.
Toute amélioration est la bienvenue. :)
Avec find et cp uniquement:
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 ";"
Semblable à la solution de Paulius, mais les fichiers qui ne vous intéressent pas ne sont pas copiés, puis supprimés:
@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
Ce n’est que deux commandes simples, mais je ne le recommanderais pas, sauf si les fichiers que vous n’avez PAS besoin de copier sont petits. En effet, cela copiera TOUS les fichiers, puis supprimera ceux qui ne sont pas nécessaires à la copie.
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"
Bien sûr, la deuxième commande est un peu longue, mais ça marche!
En outre, cette approche ne vous oblige pas à télécharger et à installer des outils tiers (Windows 2000+ BATCH dispose de suffisamment de commandes pour cela).
Sous Linux et d'autres systèmes UNIX, il est facile d'utiliser la commande tar
.
$ tar cvf /tmp/full-structure.tar *data.zip *info.txt
Ensuite, vous êtes arrivé à la cible et:
$ tar xvf /tmp/full-structure.tar
Bien sûr, vous pouvez diriger la sortie du premier tar vers le second, mais le voir fonctionner par étapes est plus facile à comprendre et à expliquer. Il me manque le cd nécessaire / nouveau / chemin / dans la commande suivante - je ne me souviens tout simplement pas comment le faire maintenant. J'espère que quelqu'un d'autre pourra l'ajouter.
$ tar cvf - *data.zip *info.txt | tar xvf -
Tar (gnutar) est également disponible sur Windows, mais j'utiliserais probablement moi-même la méthode xcopy
sur cette plate-forme.
XCOPY /S folder1\data.zip copy_of_folder1
XCOPY /S folder1\info.txt copy_of_folder1
MODIFIER: si vous souhaitez conserver les dossiers vides (vous semblez devoir relire votre message), utilisez / E au lieu de / S.
À l'aide de l'interface de ligne de commande WinRAR, vous pouvez copier les noms de fichiers et / ou les types de fichiers dans une archive. Ensuite, vous pouvez extraire cette archive à l'emplacement de votre choix. Cela préserve la structure de fichier d'origine.
Je devais ajouter des fichiers d’image d’album manquants sur mon téléphone sans avoir à recopier la musique elle-même. Heureusement, la structure de répertoire était la même sur mon ordinateur et mon mobile!
j'ai utilisé:
rar a -r C:\Downloads\music.rar X:\music\Folder.jpg
- C: \ Downloads \ music.rar = Archive à créer
- X: \ music \ = Dossier contenant des fichiers de musique
- Folder.jpg = Nom du fichier que je voulais copier
Ceci a créé une archive avec tous les fichiers Folder.jpg dans les sous-répertoires appropriés.
Cette technique peut également être utilisée pour copier des types de fichiers. Si les fichiers avaient tous des noms différents, vous pouvez choisir d'extraire tous les fichiers dans un seul répertoire. Des paramètres de ligne de commande supplémentaires peuvent archiver plusieurs types de fichiers.
Plus d'informations sur ce lien très utile http: // cects.com/using-the-winrar-command-line-tools-in-windows/
Pour ceux qui utilisent Altap Salamander (gestionnaire de fichiers à 2 panneaux): dans les options du menu contextuel Copier, spécifiez simplement les noms de fichiers ou les masques. Facile.
Les expressions régulières, les paresseux et les opposés aux installations me conviennent, j’ai donc créé un fichier de commandes qui crée le répertoire et les copie avec les commandes DOS de vanilla. Cela semble laborieux, mais plus rapide pour moi que de travailler avec robocopy.
- Créez votre liste de fichiers source avec les chemins complets, y compris la lettre du lecteur, si nécessaire, dans un fichier texte.
- Activez les expressions régulières dans votre éditeur de texte.
- Ajoutez des guillemets doubles autour de chaque ligne en cas d'espaces - chaîne de recherche
(. *)
remplace la chaîne"1"
, puis cliquez sur Tout remplacer .
- Créez deux lignes par fichier - une pour créer le répertoire, une pour copier le fichier (qqq sera remplacé par le chemin de destination) - chaîne de recherche
(. *)
remplace la chaînemd qqq \ 1 \ nxcopy \ 1 qqq \ 1 \ n
et cliquez sur remplacer tout - Supprimez le nom de fichier des chemins de destination & # 8211; rechercher
\\ ([^ \\ ^ "] +)" \ n
remplacer\\ "\ n
- Remplacez dans le chemin de destination (dans cet exemple,
A: \ src
etB: \ dest
). Désactivez les expressions régulières, recherchezqqq " A: \ src \
, remplacezB: \ dest \
et cliquez sur Tout remplacer.
md créera des répertoires imbriqués. copy se comporterait probablement de la même manière que xcopy dans cet exemple. Vous voudrez peut-être ajouter / Y à xcopy pour supprimer les confirmations d’écrasement. Vous vous retrouvez avec un fichier de commandes comme ceci:
md "B:\dest\a\b\c\"
xcopy "C:\src\a\b\c\e.xyz" "B:\dest\a\b\c\e.xyz"
répété pour chaque fichier de votre liste d'origine. Testé sur Win7.
Pour cela faire un glisser-déposer, utilisez Winzip avec une option de préservation de la structure de répertoires. Créez simplement un nouveau fichier .zip au niveau du répertoire qui sera votre racine et faites-y glisser les fichiers.
Pour copier tous les fichiers texte dans G: et conserver la structure de répertoires:
xcopy *.txt /s G: