Come copiare una struttura di directory ma includere solo determinati file (utilizzando file batch di Windows)


103

Come dice il titolo, come posso copiare in modo ricorsivo una struttura di directory ma includere solo alcuni file. Ad esempio data la seguente struttura di directory:

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

I file data.zip e info.txt possono apparire ovunque nella struttura della directory. Come posso copiare l'intera struttura della directory, ma includere solo file denominati data.zip e info.txt (tutti gli altri file dovrebbero essere ignorati)?

La struttura della directory risultante dovrebbe essere simile a questa:

copy_of_folder1
  folder2
    folder3
      data.zip
      info.txt
    folder4
    folder5
      data.zip

Risposte:


169

Non dici se deve essere solo batch, ma se puoi usarlo ROBOCOPY, prova questo:

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

EDIT: modificato il /Sparametro /Eper includere cartelle vuote.


Posso copiare * .zip con questa sintassi? Ho provato a scrivere * .zip invece di data.zip, ma non ha copiato i file, solo le cartelle. Ho anche provato? .Zip
Niels Brinch

@ Niels Brinch Sì, dovresti essere in grado di farlo. Qual è la riga di comando esatta che stai utilizzando?
aphoria

1
ROBOCOPY C: \ Source C: \ Destination * .zip / E
Niels Brinch,

Strano. Che sistema operativo stai usando? Disponi delle autorizzazioni necessarie per file / cartelle? Ho appena provato su Win 7 e *.zipho lavorato per me.
aphoria

Veramente!? Sto anche usando Win 7. Quando provo, semplicemente non copia alcun file. Solo cartelle. Ci riproverò (già che ci siamo, qual è la sintassi per includere più di * .zip - diciamo * .zip e * .jpg.
Niels Brinch,

29

Una soluzione alternativa che copia un file alla volta e non richiede 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'istruzione for esterna genera qualsiasi possibile combinazione di percorso della sottodirectory in SOURCE_DIRe del nome in FILENAMES_TO_COPY. Per ogni file esistente viene richiamato xcopy. FILE_INTERMEDIATE_DIRcontiene il percorso della sottodirectory del file all'interno del SOURCE_DIRquale deve essere creato in DEST_DIR.


1
Avevo bisogno di copiare tutte le foto da cartelle e sottocartelle, questo script batch mi ha aiutato. Ho appena cambiato la linea set FILENAMES_TO_COPY=data.zip info.txtsopra inset FILENAMES_TO_COPY=*.jpg
Kai Noack

Ricevo un errore perché il percorso del file contiene spazi (SOURCE_DIR = "C: \ Origin Test", DEST_DIR = "C: \ Dest Test", errore: Test "" era imprevisto in questo momento). Ho provato a cambiare% var% con! Var! ovunque, ma senza successo. Qualche indizio su come risolvere questo problema? L'intera struttura è piena di nomi di cartelle con spazi.
ricardo.scholz

1
Prova set "SOURCE_DIR=C:\Origin Test"e set "DEST_DIR=C:\Dest Test". Nota il posizionamento delle virgolette doppie.
sakra

13

provare a convogliare l'output di find (ad esempio il percorso del file) in cpio

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

cpio controlla il timestamp sui file di destinazione, quindi è sicuro e veloce.

rimuovere -v per operazioni più veloci, una volta che ci si abitua.


2
@Christian ha una dipendenza da cpio che non fa parte dell'installazione standard.
Crashworks

8

Se Powershell è un'opzione, puoi farlo:

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

Lo svantaggio principale è che copia tutte le cartelle, anche se finiranno per essere vuote perché nessun file corrisponde al filtro specificato. Quindi potresti ritrovarti con un albero pieno di cartelle vuote, oltre alle poche cartelle che hanno i file che desideri.


Eseguendolo una seconda volta cambierà la destinazione. (Mette i file in una sottocartella.) È un comportamento stupido se me lo chiedi. Ti consigliamo di eseguire rm -r -ErrorAction:SilentlyContinue d:\destinationPathprima di copiare per risolverlo.
MakotoE

7

Grazie alle risposte precedenti. :)

Questo script denominato "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

Accetta variabili di "Source", "Destination" e "FileName". Può anche copiare solo il tipo specificato di file o nomi di file selettivi.

Qualsiasi miglioramento è il benvenuto. :)


5

Solo con find e 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

Simile alla soluzione di Paulius, ma i file che non ti interessano non vengono copiati e quindi eliminati:

@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

Per copiare tutti i file di testo in G: e preservare la struttura delle directory:

xcopy *.txt /s G:

può funzionare in modo ricorsivo, come copiare tutto .txt dalle sottocartelle e preservare la struttura della directory relativa alla directory di base?
Micka

3

Sono solo due semplici comandi, ma non lo consiglierei, a meno che i file che NON è necessario copiare siano piccoli. Questo perché questo copierà TUTTI i file e quindi rimuoverà i file che non sono necessari nella copia.

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"

Certo, il secondo comando è un po 'lungo, ma funziona!

Inoltre, questo approccio non richiede il download e l'installazione di strumenti di terze parti (Windows 2000+ BATCH ha abbastanza comandi per questo).


Molte grazie. Come hai detto, non è l'ideale, perché (nel mio caso) i file che devono essere copiati sono solitamente piccoli, mentre i file che non dovrebbero essere copiati sono più grandi (e potrebbero essercene molti).
M4N

2

Sotto Linux e altri sistemi UNIX, l'utilizzo del tarcomando lo farebbe facilmente.

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

Quindi dovresti cwd al bersaglio e:

$ tar xvf /tmp/full-structure.tar 

Ovviamente potresti convogliare l'output dal primo tar al secondo, ma vederlo funzionare in più passaggi è più facile da capire e spiegare. Mi manca il cd necessario / to / new / path / nel seguente comando - semplicemente non ricordo come farlo ora. Qualcun altro può aggiungerlo, si spera.

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

Tar (gnutar) è disponibile anche su Windows, ma probabilmente userei il xcopymetodo io stesso su quella piattaforma.


tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt ha funzionato per me
ssinganamalla

Sia "tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt" e "tar cvf /tmp/full-structure.tar * data.zip * info.txt" mi hanno dato 3 errori : (1) "tar: * data.zip: Cannot stat: No such file or directory", (2) "tar * info.txt: Cannot stat: No such file or directory", (3) "tar: Uscita con stato di guasto a causa di errori precedenti ". Da quale cartella faccio tutto questo? Non capisco questo metodo.
user1271772

La domanda dice WINDOWS
Anfelipe

Win10 ha WSL, che lo rende valido. tar è disponibile su Windows da più di 20 anni e l'uso di una pipe ha funzionato sin dai tempi di MS-DOS. In qualsiasi ambiente shell, il PWD è importante. PWD - presente directory di lavoro. Ammetto che questa soluzione è meno per gli utenti finali e più per utenti esperti o programmatori.
JohnP

1
XCOPY /S folder1\data.zip copy_of_folder1  
XCOPY /S folder1\info.txt copy_of_folder1

EDIT: Se vuoi conservare le cartelle vuote (che, rileggendo il tuo post, ti sembra di usare) usa / E invece di / S.


1
non preserva la struttura delle cartelle.
Paulius

L'opzione / E preserva la struttura delle cartelle, inclusa la creazione di cartelle vuote se necessario. Il nome del file funziona anche con un carattere jolly (ad esempio cartella1 \ *. Zip). Ottengo solo l'errore "File non trovato" quando gli passo un nome file completo che non esiste (nel qual caso ottengo "File non trovato - xxx.xxx 0 File copiati". Quando gli do un modello che non restituisce file (ad esempio cartella1 \ *. zzz), ottengo solo "0 File (* s) copiati".
gkrogers

1

Utilizzando l'interfaccia della riga di comando di WinRAR, è possibile copiare i nomi di file e / oi tipi di file in un archivio. Quindi puoi estrarre quell'archivio in qualsiasi posizione tu voglia. Ciò preserva la struttura del file originale.

Avevo bisogno di aggiungere i file delle immagini degli album mancanti al mio telefono cellulare senza dover ricopiare la musica stessa. Fortunatamente la struttura delle directory era la stessa sul mio computer e sul cellulare!

Ero solito:

   rar a -r C:\Downloads\music.rar X:\music\Folder.jpg
  • C: \ Downloads \ music.rar = Archivio da creare
  • X: \ music \ = Cartella contenente file musicali
  • Folder.jpg = Nome file che volevo copiare

Questo ha creato un archivio con tutti i file Folder.jpg nelle sottodirectory appropriate.

Questa tecnica può essere utilizzata anche per copiare i tipi di file. Se i file avevano tutti nomi diversi, è possibile scegliere di estrarre tutti i file in una singola directory. Ulteriori parametri della riga di comando possono archiviare più tipi di file.

Maggiori informazioni in questo link molto utile http://cects.com/using-the-winrar-command-line-tools-in-windows/


1

Per chi utilizza Altap Salamander (file manager a 2 pannelli): nelle Opzioni del popup Copia, basta specificare i nomi dei file o le maschere. Facile.


0

Sto bene con le espressioni regolari, pigro e contrario alle installazioni, quindi ho creato un file batch che crea la directory e copia con i comandi DOS vanilla. Sembra laborioso ma più veloce per me che elaborare Robocopy.

  1. Crea il tuo elenco di file di origine con percorsi completi, inclusa la lettera di unità se nca, in un file di testo.
  2. Attiva le espressioni regolari nel tuo editor di testo.
  3. Aggiungi virgolette doppie attorno a ogni riga in caso di spazi: stringa di ricerca (.*)sostituisci stringa"\1" e fai clic su sostituisci tutto
  4. Crea due righe per file: una per creare la directory, una per copiare il file (qqq verrà sostituito con il percorso di destinazione): cerca stringa (.*)sostituisci stringa md qqq\1\nxcopy \1 qqq\1\ne fai clic su Sostituisci tutto
  5. Rimuovi il nome del file dai percorsi di destinazione - cerca \\([^\\^"]+)"\nsostituisci\\"\n
  6. Sostituisci nel percorso di destinazione (in questo esempio A:\srce B:\dest). Disattiva le espressioni regolari, cerca qqq"A:\src\sostituisci B:\dest\e fai clic su sostituisci tutto.

md creerà directory annidate. copy probabilmente si comporterebbe in modo identico a xcopy in questo esempio. Potresti voler aggiungere / Y a xcopy per eliminare le conferme di sovrascrittura. Finisci con un file batch in questo modo:

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

ripetuto per ogni file nell'elenco originale. Testato su Win7.


-1

Per fare questo con il drag and drop usa winzip c'è un'opzione di conservazione della struttura delle directory. Crea semplicemente un nuovo .zip a livello di directory che sarà la tua radice e trascina i file all'interno.


Grazie, ma stavo cercando una soluzione da utilizzare da file di script (batch). Quindi, niente drag & drop ...
M4N
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.