Cara menyalin struktur direktori tetapi hanya menyertakan file tertentu (menggunakan file batch windows)

103

Seperti judulnya, bagaimana saya bisa menyalin struktur direktori secara rekursif tetapi hanya menyertakan beberapa file. Misalnya, diberikan struktur direktori berikut:

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

File data.zip dan info.txt dapat muncul di mana saja dalam struktur direktori. Bagaimana cara menyalin struktur direktori lengkap, tetapi hanya menyertakan file bernama data.zip dan info.txt (semua file lain harus diabaikan)?

Struktur direktori yang dihasilkan akan terlihat seperti ini:

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

Jawaban:

169

Anda tidak menyebutkan apakah itu harus batch saja, tetapi jika Anda bisa menggunakan ROBOCOPY, coba ini:

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

EDIT: Mengubah /Sparameter /Euntuk menyertakan folder kosong.

aphoria
sumber
Bisakah saya menyalin * .zip dengan sintaks ini? Saya mencoba hanya menulis * .zip daripada data.zip, tetapi tidak menyalin file, hanya foldernya. Saya juga mencoba? .Zip
Niels Brinch
@Niels Brinch Ya, Anda harus bisa melakukan itu. Apa baris perintah persis yang Anda gunakan?
aphoria
1
ROBOCOPY C: \ Source C: \ Destination * .zip / E
Niels Brinch
Aneh. OS apa yang Anda gunakan? Apakah Anda memiliki izin file / folder yang diperlukan? Saya baru saja menguji Win 7 dan *.zipbekerja untuk saya.
aphoria
Betulkah!? Saya juga menggunakan Win 7. Ketika saya mencoba, itu tidak menyalin file apa pun. Hanya folder. Saya akan mencoba lagi. (sementara kita melakukannya, sintaks apa yang menyertakan lebih dari * .zip - katakanlah * .zip dan * .jpg.
Niels Brinch
29

Solusi alternatif yang menyalin satu file pada satu waktu dan tidak memerlukan 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!"
    )
)

Pernyataan outer for menghasilkan kombinasi jalur yang mungkin dari subdirektori in SOURCE_DIRdan name in FILENAMES_TO_COPY. Untuk setiap file yang ada, xcopy dipanggil. FILE_INTERMEDIATE_DIRmemegang jalur subdirektori file yang di SOURCE_DIRdalamnya perlu dibuat DEST_DIR.

sakra
sumber
1
Saya perlu menyalin semua foto dari folder dan subfolder, skrip batch ini membantu. Baru saja mengubah baris di set FILENAMES_TO_COPY=data.zip info.txtatas menjadiset FILENAMES_TO_COPY=*.jpg
Kai Noack
Saya mendapatkan kesalahan karena jalur file memiliki spasi di atasnya (SOURCE_DIR = "C: \ Origin Test", DEST_DIR = "C: \ Dest Test", error: Test "" tidak terduga saat ini). Saya sudah mencoba mengubah% var% oleh! Var! di mana-mana, tapi tidak berhasil. Ada petunjuk tentang cara mengatasi ini? Seluruh struktur penuh dengan nama folder dengan spasi.
ricardo.scholz
1
Coba set "SOURCE_DIR=C:\Origin Test"dan set "DEST_DIR=C:\Dest Test". Perhatikan penempatan tanda kutip ganda.
sakra
13

coba piping keluaran find (mis. path file) ke cpio

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

cpio memeriksa stempel waktu pada file target - jadi aman dan cepat.

hapus -v untuk operasi yang lebih cepat, setelah Anda terbiasa.

Gabe Rainbow
sumber
2
@Christian memiliki ketergantungan pada cpio yang bukan bagian dari instalasi standar.
Crashworks
8

Jika Powershell adalah opsi, Anda dapat melakukan ini:

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

Kerugian utamanya adalah menyalin semua folder, bahkan jika folder itu akan kosong karena tidak ada file yang cocok dengan filter yang Anda tentukan. Jadi Anda bisa berakhir dengan pohon yang penuh dengan folder kosong, selain beberapa folder yang memiliki file yang Anda inginkan.

Neil
sumber
Menjalankan ini untuk kedua kalinya akan mengubah tujuan. (Ini menempatkan file dalam subfolder.) Ini adalah perilaku konyol jika Anda bertanya kepada saya. Anda akan ingin menjalankan rm -r -ErrorAction:SilentlyContinue d:\destinationPathsebelum menyalin untuk memperbaikinya.
MakotoE
7

Terima kasih Untuk Jawaban Sebelumnya. :)

Skrip ini bernama "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

Ini menerima variabel "Sumber", "Tujuan", dan "Nama File". Itu juga hanya dapat menyalin jenis file tertentu atau nama file selektif.

Perbaikan apapun dipersilakan. :)

Rhak Kahr
sumber
5

Dengan hanya temukan dan 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 ";"
Rop
sumber
4

Mirip dengan solusi Paulius, tetapi file yang tidak Anda pedulikan tidak disalin kemudian dihapus:

@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
Patrick Cuff
sumber
4

Untuk menyalin semua file teks ke G: dan mempertahankan struktur direktori:

xcopy *.txt /s G:
Osbert Snudge
sumber
dapatkah ini bekerja secara rekursif, seperti menyalin semua .txt dari subfolder dan mempertahankan struktur direktori yang berhubungan dengan direktori dasar?
Micka
3

Itu hanya dua perintah sederhana, tetapi saya tidak akan merekomendasikan ini, kecuali file yang tidak perlu Anda salin berukuran kecil. Itu karena ini akan menyalin SEMUA file dan kemudian menghapus file yang tidak diperlukan di salinan.

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"

Tentu, perintah kedua agak panjang, tetapi berhasil!

Selain itu, pendekatan ini tidak mengharuskan Anda mengunduh dan menginstal alat pihak ketiga (Windows 2000+ BATCH memiliki cukup perintah untuk ini).

Paulius
sumber
Terima kasih banyak. Seperti yang Anda sebutkan, itu tidak ideal, karena (dalam kasus saya) file yang harus disalin biasanya berukuran kecil, sedangkan file yang tidak boleh disalin berukuran lebih besar (dan mungkin banyak).
M4N
2

Di Linux dan sistem UNIX lainnya, menggunakan tarperintah akan melakukan ini dengan mudah.

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

Kemudian Anda akan beralih ke target dan:

$ tar xvf /tmp/full-structure.tar 

Tentu saja Anda bisa menyalurkan output dari tar pertama ke tar ke-2, tetapi melihatnya bekerja dalam langkah-langkah lebih mudah untuk dipahami dan dijelaskan. Saya kehilangan cd / ke / new / path / yang diperlukan dalam perintah berikut - saya tidak ingat bagaimana melakukannya sekarang. Semoga orang lain dapat menambahkannya.

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

Tar (gnutar) juga tersedia di Windows, tetapi saya mungkin akan menggunakan xcopymetode ini sendiri di platform itu.

JohnP
sumber
tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt bekerja untuk saya
ssinganamalla
Baik "tar cvf /tmp/full-structure.tar ** / data.zip ** / info.txt" dan "tar cvf /tmp/full-structure.tar * data.zip * info.txt" memberi saya 3 kesalahan : (1) "tar: * data.zip: Tidak bisa stat: Tidak ada file atau direktori", (2) "tar * info.txt: Tidak bisa stat: Tidak ada file atau direktori seperti itu", (3) "tar: Keluar dengan status kegagalan karena kesalahan sebelumnya ". Dari folder mana saya melakukan semua ini? Saya tidak mengerti metode ini.
pengguna1271772
Pertanyaannya mengatakan WINDOWS
Anfelipe
Win10 memiliki WSL, yang membuat ini valid. tar telah tersedia di Windows selama 20+ tahun dan penggunaan pipa telah bekerja sejak MS-DOS. Di lingkungan shell mana pun, PWD itu penting. PWD - sekarang direktori kerja. Saya akui solusi ini lebih sedikit untuk pengguna akhir dan lebih untuk pengguna daya atau pemrogram.
JohnP
1
XCOPY /S folder1\data.zip copy_of_folder1  
XCOPY /S folder1\info.txt copy_of_folder1

EDIT: Jika Anda ingin mempertahankan folder kosong (yang, saat membaca ulang posting Anda, sepertinya Anda) gunakan / E daripada / S.

gkrogers
sumber
1
itu tidak mempertahankan struktur folder.
Paulius
Opsi / E mempertahankan struktur folder, termasuk membuat folder kosong jika perlu. Nama file juga bekerja dengan wildcard (misalnya folder1 \ *. Zip). Saya hanya mendapatkan "File tidak ditemukan error" ketika saya memberikan nama file lengkap yang tidak ada (dalam hal ini saya mendapatkan "File tidak ditemukan - xxx.xxx 0 File disalin". Ketika saya memberikan pola yang tidak mengembalikan file (misalnya folder1 \ *. zzz), saya hanya mendapatkan "0 File (* s) disalin".
gkrogers
1

Menggunakan antarmuka baris perintah WinRAR, Anda dapat menyalin nama file dan / atau jenis file ke arsip. Kemudian Anda dapat mengekstrak arsip itu ke lokasi mana pun yang Anda suka. Ini mempertahankan struktur file asli.

Saya perlu menambahkan file gambar album yang hilang ke ponsel saya tanpa harus menyalin ulang musik itu sendiri. Untungnya struktur direktori di komputer dan ponsel saya sama!

Saya menggunakan:

   rar a -r C:\Downloads\music.rar X:\music\Folder.jpg
  • C: \ Downloads \ music.rar = Arsip yang akan dibuat
  • X: \ music \ = Folder berisi file musik
  • Folder.jpg = Nama file yang ingin saya salin

Ini membuat arsip dengan semua file Folder.jpg di subdirektori yang tepat.

Teknik ini juga dapat digunakan untuk menyalin jenis file. Jika semua file memiliki nama yang berbeda, Anda dapat memilih untuk mengekstrak semua file ke satu direktori. Parameter baris perintah tambahan dapat mengarsipkan beberapa jenis file.

Informasi lebih lanjut di tautan yang sangat membantu ini http://cects.com/using-the-winrar-command-line-tools-in-windows/

Jim_Joat
sumber
1

Bagi mereka yang menggunakan Altap Salamander (pengelola file 2 panel): dalam Opsi popup Salin, cukup tentukan nama file atau topeng. Mudah.

Hugo P.
sumber
0

Saya baik-baik saja dengan ekspresi reguler, malas dan tidak suka menginstal, jadi saya membuat file batch yang membuat direktori dan menyalin dengan perintah vanilla DOS. Kelihatannya melelahkan tetapi lebih cepat bagi saya daripada mengerjakan robocopy.

  1. Buat daftar file sumber Anda dengan jalur lengkap, termasuk huruf drive jika nec, dalam file teks.
  2. Aktifkan ekspresi reguler di editor teks Anda.
  3. Tambahkan tanda kutip ganda di setiap baris jika ada spasi - cari string (.*)ganti string "\1", dan klik ganti semua
  4. Buat dua baris per file - satu untuk membuat direktori, satu untuk menyalin file (qqq akan diganti dengan jalur tujuan) - cari string (.*)ganti string md qqq\1\nxcopy \1 qqq\1\ndan klik ganti semua
  5. Hapus nama file dari jalur tujuan - cari \\([^\\^"]+)"\nganti\\"\n
  6. Ganti di jalur tujuan (dalam contoh ini A:\srcdan B:\dest). Matikan ekspresi reguler, cari qqq"A:\src\ganti B:\dest\dan klik ganti semua.

md akan membuat direktori bersarang. copy mungkin akan berperilaku identik dengan xcopy dalam contoh ini. Anda mungkin ingin menambahkan / Y ke xcopy untuk menyembunyikan konfirmasi penimpaan. Anda berakhir dengan file batch seperti ini:

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

diulang untuk setiap file dalam daftar asli Anda. Diuji di Win7.

Chris
sumber
-1

Untuk melakukan ini dengan drag and drop menggunakan winzip ada opsi pelestarian struktur dir. Cukup buat .zip baru di tingkat direktori yang akan menjadi root Anda dan seret file.

Gnoy Dav
sumber
Terima kasih, tetapi saya sedang mencari solusi untuk digunakan dari file skrip (batch). Jadi, tidak ada seret & lepas ...
M4N