Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Батник сбора файлов из поддиректорий в общую папку (http://forum.oszone.net/showthread.php?t=132886)

rBBWYwg 23-02-2009 17:01 1046536

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

Имеем многоуровневую развитую структуру директорий "Главная-подчиненные". Например,

GENERALFOLDER
|_FOLDER-1
|_FOLDER-11
|_FOLDER-111
|_FOLDER-1111
|_FOLDER-1112
...
|_FOLDER-112
...
|_FOLDER-2
...

и т.д.
Количество подчиненных директорий не фиксировано.
Есть ли способ написать батник, который бы перемещал все файлы поддиректорий в их корневую папку? То есть, все файлы из любых поддиректорий папки FOLDER-1 перемещались бы в FOLDER-1, все файлы поддиректорий из FOLDER-2 перемещались бы в FOLDER-2, так же с FOLDER-3 и т.д.
При этом, необходимо избежать переписывания файлов при совпадений их имен, а оригинальными именами файлов можно жертвовать, но не расширениями.

amel27 24-02-2009 08:59 1047075

можно, но из схемы не видна вложенность подкаталогов, к примеру, является ли FOLDER-11 подкаталогом FOLDER-1 ?.. Наконец, недостаточно полно описан алгоритм разрешения конфликтов имен, что значит "именами файлов можно жертвовать, но не расширениями"? переименовывать при совпадении?.. но тогда по какому правилу?.. или затирать?.. но тогда какой из двух файлов?

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

@Echo Off

Set $SRC=C:\GENERALFOLDER\FOLDER-1\*.*
Set $DST=C:\GENERALFOLDER\FOLDER-1\

If Not Exist %$DST% MD %$DST% 2>Nul
If Not Exist
%$DST% (
    @Echo Ошибка! Целевой каталог не обнаружен.
    Exit
)
For /F "Delims=" %%i In ('DIR /B/S/A:-D "%$SRC%"') Do (
    If Not Exist "%$DST%%%~nxi" Move "%%i" "%$DST%"
)

еще один пример: http://forum.oszone.net/showthread.p...297#post922297

rBBWYwg 24-02-2009 10:45 1047197

amel27
Спасибо за ответ.
Да, имелось ввиду, что FOLDER 111 - это подкаталог папки FOLDER-11, которая в свою очередь является подкаталогом папки FOLDER-1. А в отношении жертвоприношений имен файлов имелась ввиду допустимость изменять их как угодно в целях сохранения самого файла - переименовывать по любому правилу при совпадении (полное переименование, добавление символа, цифры, и т.д., но с сохранением расширения).
Сегодня опробую Ваш код на живом материале, благодарю.

amel27 24-02-2009 11:46 1047269

Цитата:

Цитата rBBWYwg
имелось ввиду »

тогда примерно так:
Код:

@Echo Off

Set MASK=*.*
Set ROOT=C:\GENERALFOLDER

For /F "Delims=" %%a In ('2^>nul DIR /B/S/A:D %ROOT%\*') Do (
  For /F "Delims=" %%i In ('2^>nul DIR /B/S/A:-D "%%a\%MASK%"') Do (
      Call :FileGetNewName "%%i" "%ROOT%"
      Call :FileMove "%%i"
  )
)

Exit

:FileMove
:: ---
:: %1 - полное имя исходного файла, включая путь
:: ---

Echo From: %~1
Echo To  : %$N%%$I%%$X%
Echo.
Move "%~1" "%FileGetNewName%" >Nul

GoTo
:EOF

:FileGetNewName
:: ---
:: %1 - полное имя исходного файла, включая путь
:: %2 - путь к целевому каталогу
:: ---

Set $I=
Set FileGetNewName=

If Not Exist "%~1" GoTo :EOF
For %%i In ("%~1") Do Set $N=%%~ni
For %%i In ("%~1") Do Set $X=%%~xi

:FileGetNewName_LOOP

Set FileGetNewName=%~2\%$N%%$I%%$X%
If Not Exist "%FileGetNewName%" GoTo :EOF
Set /A $I +=1
GoTo FileGetNewName_LOOP


rBBWYwg 16-03-2009 16:30 1065553

amel27,
большое спасибо за помощь. Но оказалось, что CMD крайне долго обрабатывает мой объем файлов (порядка 10 тысяч), при этом делая много ошибок - пропускает некоторые папки, не добираясь до файлов. Вероятно, существуют какие-то количественные ограничения. К тому же, некоторые файлы просто не воспринимаются самой консолью из-за неудобоваримых имен. Поэтому я нашла способ формировать батник ПРЯМОГО поименного копирования с указанием пути от каждого файла в корневую папку. В работе сэкономила массу времени и избежала ошибок.
НО!!!
Не избежала потери информации, когда имена файлов из разных папок совпадают. Они просто замещают уже имеющийся.

Прошу помочь снова. Можно ли каким-то образом, используя прямые пути копирования файлов из субдиректорий в директории вида
copy /y /n "C:\FOLDER\SUBFOLDER\*.*" "C:\FOLDER\"
сформировать дополнительное условие дополнения имен счетчиком, если в целевой директории лежит файл с тем же именем?

amel27 17-03-2009 08:58 1066078

Цитата:

Цитата rBBWYwg
CMD крайне долго обрабатывает мой объем файлов »

команды Echo из скрипта пробовали убирать?

Цитата:

Цитата rBBWYwg
пропускает некоторые папки, не добираясь до файлов. Вероятно, существуют какие-то количественные ограничения »

надо конкретно смотреть, мне известно только ограничение на длину имени файла+путь до 255 символов

Цитата:

Цитата rBBWYwg
copy /y /n "C:\FOLDER\SUBFOLDER\*.*" "C:\FOLDER\" »

но это не "батник ПРЯМОГО поименного копирования с указанием пути от каждого файла", а копирование содержимого каталога по маске

Цитата:

Цитата rBBWYwg
дополнительное условие дополнения имен счетчиком, если в целевой директории лежит файл с тем же именем »

средствами COPY никак, могу только привести кусок из приведенного выше скрипта:
Код:

For %%i In ("C:\FOLDER\SUBFOLDER\*.*") Do (
  Call :FileGetNewName "%%i" "C:\FOLDER"
  Call :FileCopy "%%i" )
Exit

:FileCopy
 Copy "%~1" "%FileGetNewName%" >Nul
 GoTo :EOF

:FileGetNewName
 Set $I=
 Set FileGetNewName=
 If Not Exist "%~1" GoTo :EOF
 For %%i In ("%~1") Do Set $N=%%~ni&$X=%%~xi
:FileGetNewName_LOOP
 Set FileGetNewName=%~2\%$N%%$I%%$X%
 If Not Exist "%FileGetNewName%" GoTo :EOF
 Set /A $I +=1
 GoTo FileGetNewName_LOOP


rBBWYwg 17-03-2009 12:13 1066232

amel27,
Поняла, спасибо.
На счет ограничений и тормозящего эффекта Echo для меня информация совершенно новая. Проверила через Excel - действительно, некоторые пути+файлы больше 255 знаков. Эффект от Echo не замеряла.
Посмотрите, пожалуйста, личку - отправлю вопрос, на который прошу ответить так же в личку.

Arsenik77 05-08-2011 20:23 1726573

Можете подправить этот батник так,
Цитата:

Цитата amel27
код: »

чтоб он перемещал файлы из под под...директорий в их первую директорию, например: есть такая структура
GENERALFOLDER
|_FOLDER-1
|_FOLDER-11
|_FOLDER-111
|_FOLDER-1111
|_FOLDER-1112
чтоб все файлы из поддиректорий |_FOLDER-1112 |_FOLDER-1111 |_FOLDER-111 |_FOLDER-11 переместились в |_FOLDER-1
при этом если в |_FOLDER-1 нет поддиректорий, то ее не надо трогать т.е. перемещать файлы из нее в GENERALFOLDER.

Foreigner 13-08-2011 21:21 1731228

Arsenik77, Как-то так
Код:

@echo off
setlocal

for /d %%i in ("generalfolder\*") do (

    pushd "%%i"
    for /d %%j in (*) do (
   
        for /f "tokens=*" %%k in (' "2>nul dir /b /s /a-d "%%j"" ') do call:move "%%k"

    )
    popd
   
)
goto:eof

:move
set "file=%~nx1"

:check
set /a cnt+=1
if exist "%file%" set "file=%~n1(%cnt%)%~x1" && goto:check

move %1 "%file%"
set "cnt="
set "file="


Arsenik77 17-08-2011 22:17 1734144

Цитата:

Цитата Foreigner
Как-то так »

Помоги прикрутить к твоему батнику вот этот батник (удаление файлов по маске).
Нужно чтобы в директориях оставались только определенные файлы.

Код:

chcp 1251
for %%i in (jpg mp3) do set $.%%i=_
for %%i in ("c:\temp and music\"*) do if not defined $%%~xi (
del /s/f/q "%%i"
echo.%%i >>lod_del_files.txt
)


Foreigner 17-08-2011 23:46 1734184

Arsenik77,
Код:

@echo off
setlocal

set "exclude=.txt .jpg .mp3"

for /d %%i in ("generalfolder\*") do (

    pushd "%%i"
    for /d %%j in (*) do (
   
        for /f "tokens=*" %%k in (' "2>nul dir /b /s /a-d "%%j"" ') do call:move "%%k"

    )
    popd
   
)
goto:eof

:move
for %%i in (%exclude%) do if /i "%%i"=="%~x1" goto:eof
set "file=%~nx1"

:check
set /a cnt+=1
if exist "%file%" set "file=%~n1(%cnt%)%~x1" && goto:check

move %1 "%file%"
set "cnt="
set "file="


Arsenik77 18-08-2011 10:12 1734336

Батник не правильно работает, нужно удалять все файлы, кроме "exclude=.txt .jpg .mp3" и затем оставшиеся файлы перемещать в свою первую директорию.
Сейчас он просто перемещает "не нужные" в свою первую директорию, а "нужные" оставляет на месте.

Foreigner 18-08-2011 10:55 1734369

Arsenik77,
Т.е. те, что исключение перемещать в корень, а остальные удалять?
Код:

@echo off
setlocal

set "exclude=.txt .jpg .mp3"

for /d %%i in ("generalfolder\*") do (

    pushd "%%i"
    for /d %%j in (*) do (
   
        for /f "tokens=*" %%k in (' "2>nul dir /b /s /a-d "%%j"" ') do call:move "%%k"

    )
    popd
   
)
goto:eof

:move
for %%i in (cnt file check) do set "%%i="

for %%i in (%exclude%) do if /i "%%i"=="%~x1" set check=1
if not defined check del /a /q /f %1 && goto:eof

set "file=%~nx1"

:check
set /a cnt+=1
if exist "%file%" set "file=%~n1(%cnt%)%~x1" && goto:check

move %1 "%file%"


Arsenik77 18-08-2011 21:53 1734831

Все правильно, но надо чтобы в корнях тоже оставались только исключения.

Foreigner 18-08-2011 22:16 1734847

Цитата:

Цитата Arsenik77
но надо чтобы в корнях тоже оставались только исключения. »

Код:

@echo off
setlocal

set "exclude=.txt .jpg .mp3"

for /d %%i in ("generalfolder\*") do (

    pushd "%%i"
    for /f "tokens=*" %%j in ('dir /b /s /a-d') do call:move "%%j"
    popd
   
)
goto:eof

:move
for %%i in (cnt file check) do set "%%i="

for %%i in (%exclude%) do if /i "%%i"=="%~x1" set check=1
if not defined check del /a /q /f %1 && goto:eof

set "file=%~nx1"

:check
set /a cnt+=1
if exist "%file%" set "file=%~n1(%cnt%)%~x1" && goto:check

move %1 "%file%"


Arsenik77 19-08-2011 19:47 1735417

В корне файлы переименовываются дописывается "(1)" при повторном запуске батника.
читать дальше »
Для меня это существенно, считаю задачу решенной.
Спасибо!

Foreigner 19-08-2011 20:16 1735426

Цитата:

Цитата Arsenik77
В корне файлы переименовываются дописывается "(1)" при повторном запуске батника. »

Код:

@echo off
setlocal

set "exclude=.jpg .mp3 .txt"

for /d %%i in ("generalfolder\*") do (

    pushd "%%i"
    for /f "tokens=*" %%j in ('dir /b /s /a-d') do call:move "%%j"
    popd
   
)
goto:eof

:move
for %%i in (cnt file check) do set "%%i="

for %%i in (%exclude%) do if /i "%%i"=="%~x1" set check=1
if not defined check del /a /q /f %1 && goto:eof
if "%~dp1"=="%cd%\" goto:eof

set "file=%~nx1"

:check
set /a cnt+=1
if exist "%file%" set "file=%~n1(%cnt%)%~x1" && goto:check

1>nul move %1 "%file%"


Arsenik77 05-02-2012 16:14 1852257

Помогите дописать последний батник так, чтобы если количество файлов (результирующее т.е. после отработки основного батника) в папке меньше 5 то файлы из нее перемещались в другую папку, например папку "различное".


Время: 23:51.

Время: 23:51.
© OSzone.net 2001-