Войти

Показать полную графическую версию : [решено] Батник сбора файлов из поддиректорий в общую папку


rBBWYwg
23-02-2009, 17:01
Уважаемые, прошу помощи по такому вопросу:

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

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
можно, но из схемы не видна вложенность подкаталогов, к примеру, является ли 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.php?p=922297#post922297

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

amel27
24-02-2009, 11:46
имелось ввиду »
тогда примерно так:
@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
amel27,
большое спасибо за помощь. Но оказалось, что CMD крайне долго обрабатывает мой объем файлов (порядка 10 тысяч), при этом делая много ошибок - пропускает некоторые папки, не добираясь до файлов. Вероятно, существуют какие-то количественные ограничения. К тому же, некоторые файлы просто не воспринимаются самой консолью из-за неудобоваримых имен. Поэтому я нашла способ формировать батник ПРЯМОГО поименного копирования с указанием пути от каждого файла в корневую папку. В работе сэкономила массу времени и избежала ошибок.
НО!!!
Не избежала потери информации, когда имена файлов из разных папок совпадают. Они просто замещают уже имеющийся.

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

amel27
17-03-2009, 08:58
CMD крайне долго обрабатывает мой объем файлов »команды Echo из скрипта пробовали убирать?

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

copy /y /n "C:\FOLDER\SUBFOLDER\*.*" "C:\FOLDER\" »но это не "батник ПРЯМОГО поименного копирования с указанием пути от каждого файла", а копирование содержимого каталога по маске

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

Arsenik77
05-08-2011, 20:23
Можете подправить этот батник так, код: » чтоб он перемещал файлы из под под...директорий в их первую директорию, например: есть такая структура
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
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
Как-то так »
Помоги прикрутить к твоему батнику вот этот батник (удаление файлов по маске).
Нужно чтобы в директориях оставались только определенные файлы.

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

Foreigner
18-08-2011, 10:55
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
Все правильно, но надо чтобы в корнях тоже оставались только исключения.

Foreigner
18-08-2011, 22:16
но надо чтобы в корнях тоже оставались только исключения. »

@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
В корне файлы переименовываются дописывается "(1)" при повторном запуске батника.
Для меня это существенно, считаю задачу решенной.
Спасибо!

Foreigner
19-08-2011, 20:16
В корне файлы переименовываются дописывается "(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
Помогите дописать последний батник так, чтобы если количество файлов (результирующее т.е. после отработки основного батника) в папке меньше 5 то файлы из нее перемещались в другую папку, например папку "различное".




© OSzone.net 2001-2012