@echo off
setlocal
cd /d "%~dp0"
set "z_path=D:\test2\테스트1"
set "z_ext=flac"
set "z_file=*"
:: 폴더 리스트
for /f "usebackq delims=" %%f in (`dir /b /ad "%z_path%"`) do (
echo "%z_path%\%%~nxf"
call set /a z_num=0
for /f "usebackq delims=" %%g in (`dir /b /s "%z_path%\%%~nxf\%z_file%.%z_ext%"`) do (
call set /a z_num=%%z_num%%+1
call set z_numm=00000%%z_num%%
call set z_numm=%%z_numm:~-4%%
call move "%%g" "%z_path%\%%~nxf\%%z_numm%%.%z_ext%"
ping localhost -n 1 >nul
rd /q "%%~dpg" >nul
)
)
endlocal
pause
하위폴더의 파일을 상위폴더로 옮기는 배치파일 명령어?를 서치해서 찾았는데요,
이걸 사용하니까 작동은 잘 되는데 파일명을 0001, 0002 이런식으로 변경해서 경로이동을 하더라구요..
기존 파일명 그대로 옮기려면 어떤 부분을 삭제해줘야 할까요?ㅠㅠ 감사합니다.
setlocal
cd /d "%~dp0"
set "z_path=D:\test2\테스트1"
set "z_ext=flac"
set "z_file=*"
:: 폴더 리스트
for /f "usebackq delims=" %%f in (`dir /b /ad "%z_path%"`) do (
echo "%z_path%\%%~nxf"
call set /a z_num=0
for /f "usebackq delims=" %%g in (`dir /b /s "%z_path%\%%~nxf\%z_file%.%z_ext%"`) do (
call set /a z_num=%%z_num%%+1
call set z_numm=00000%%z_num%%
call set z_numm=%%z_numm:~-4%%
call move "%%g" "%z_path%\%%~nxf\%%z_numm%%.%z_ext%"
ping localhost -n 1 >nul
rd /q "%%~dpg" >nul
)
)
endlocal
pause
하위폴더의 파일을 상위폴더로 옮기는 배치파일 명령어?를 서치해서 찾았는데요,
이걸 사용하니까 작동은 잘 되는데 파일명을 0001, 0002 이런식으로 변경해서 경로이동을 하더라구요..
기존 파일명 그대로 옮기려면 어떤 부분을 삭제해줘야 할까요?ㅠㅠ 감사합니다.
6개의 답변이 있습니다.
자 그럼...
질문자의 목적에 맞게 비슷한 환경을 만들어 두고 실제 올린 배치 파일을 Test해 보도록 하겠습니다.
첨부 이미지와 같은 디렉터리 구조에 File들을 임의 생성해서 넣고 Test를 진행합니다.
질문자가 올린 배치 file을 test.bat라는 이름으로 d:\ 에 test.bat라는 이름으로 만들고 시작합니다.
test.bat를 실행 시키면 아래와 같은 내용을 표시되고 종료되면서 사용자 입력을 기다리는 화면이 나오네요.
실행되는 화면을 쭉~ 보면 원하지 않았던 “디렉터리가 비어 있지 않습니다.”라는 메시지가 계속 표시되고 있음을 확인할 수 있네요.
디렉터리를 지우기 위해 사용한 rd 명령에서 오류가 일부 발생하고 있는 거 겠죠.
그럼, 실제 실행된 결과를 한번 볼까요.
“sound1”의 하위 디렉터리인 “도시”, “바다” 등에 있던 flac file들이 “sound1” 디렉터리에 0001.flac ~ 0017.flac로 파일명이 숫자로 변경되어 복사되어 있는 것이 보이네요. “도시” 디렉터리에는 flac file들만 있었기 때문에 rd 명령에 의해 정상적으로 지워지고 없지만, flac가 아닌 file들이 있는 디렉터리는 다른 파일들이 남아 있어서 빈 디렉터리가 아니어서 지울수 없다는 오류 메시지가 표시되었던 것 같고요.
남아 있는 파일 정리 정도는 사람이 직접해 주는 게 안전할 것 같고, flac 파일들만 있을 경우에는 문제가 되지 않을 것 같고 해서 rd 명령 수행시 오류 메시지 정도는 그냥 넘어가도 될 것으로 보이네요.
여기까지가 질문자께서 수행한 결과이며, 질문자는 이 배치 file이 어느정도 원하는 결과를 주고 있으나 file명이 숫자로 변경되어 원래 file명을 유지할 수 있게 수정하고 싶다는 내용이 되겠네요.
간단하게 원하는 결과만 얻고 싶다면 move 명령에서 두 번째 파라미터만 살짝 수정해 주면 간단하게 해결될 수 있겠죠.
즉,
call move "%%g" "%z_path%\%%~nxf\%%z_numm%%.%z_ext%" 를,
call move "%%g" "%z_path%\%%~nxf\“
수정하면 원하는 결과를 얻을 수 있게 되는 것이죠.
그럼, 이렇게 해서 배치 파일을 한번 실행해 보도록 하겠습니다.
화면에 표시되는 메시지는 수정전이나 수정 후나 거의 유사하게 표시될 것 같고요.
실제, 결과를 확인해 볼까요.
질문자가 요구한 결과가 산출된 것 같네요.
그런데... 자세히 확인해 보면 한가지 심각한 문제점이 있네요. 동일 이름 ( ex: “숲속.flac” )이 있을 경우에 덮어씌워 버리고 있네요.
자동으로 이름을 변경해서 복사하도록 만드려면 복잡해 질 것 같고... 간단하게 할수 있는 안전 조치로 move 문에 /-y 옵션을 추가하여 사용자에게 어떻게할지 묻도록 만드는게 좋지 않을까 생각되네요.
끝으로, 불필요한 명령들을 주석 처리문인 rem으로 표시하고, 인덴테이션 처리도해서 깔끔하게 정리한 최종 배치 file을 올리면서 마무리 짓겠습니다.
:::::: 불필요한 명령들을 주석 처리 (rem 사용)
@echo off
setlocal
rem cd /d "%~dp0"
set "z_path=D:\test2\테스트1"
set "z_ext=flac"
set "z_file=*"
:: 폴더 리스트
for /f "usebackq delims=" %%f in (`dir /b /ad "%z_path%"`) do (
rem echo "%z_path%\%%~nxf"
rem call set /a z_num=0
for /f "usebackq delims=" %%g in (`dir /b /s "%z_path%\%%~nxf\%z_file%.%z_ext%"`) do (
rem call set /a z_num=%%z_num%%+1
rem call set z_numm=00000%%z_num%%
rem call set z_numm=%%z_numm:~-4%%
call move /-y "%%g" "%z_path%\%%~nxf\"
rem ping localhost -n 1 >nul
rd /q "%%~dpg" >nul
)
)
endlocal
rem pause
질문자께서 올린 배치 파일 의 명령들을 세부적으로 분석 설명해 드려 보겠습니다.
다른 분들께도 배치 File을 이해하는데 도움이 될 수 있을 거라 생각되네요.
보다 정확한 답글을 달아두어야 이상한 댓글로 인한 오해가 있을 가능성도 낮아 질거 같고요.
그럼, 첫줄 부터 시작하겠습니다.
echo off : 배치 파일 명령 수행중에 명령들이 화면에 표시되지 않게 사용하는 명령으로
이 명령이 없을 경우에는 실행하기 위한 명령과 명령에 의한 결과 값들이
함께 표시되게 되어 화면이 지저분하게 보이게 되어 실 업무에 배치 파일을 사용하게 될 경우에
대부분 제일 첫줄에 echo off 명령을 넣어 사용하게 됩니다.
@echo off 와 같이 제일 앞에 @를 붙이는 이유는 echo off 명령에 의해
이후 부터의 명령은 화면에 보이지 않게 되나, echo off라는 명령 자체는 화면에 표시되게 되기 때문에
echo off라는 명령 조차도 화면에 표시되지 않게 하기 위해 echo off 앞에 @를 붙이게 됩니다.
setlocal : 배치 파일이 실행되면서 변경되는 환경 변수,
디렉터리 경로 등이 배치 수행후 모두 원래 상태대로 남아 있게 하기 위한 명령
setlocal 다음 부터 endlocal까지 변경되는 환경값들이 endlocal로 인해
setlocal 이전 상태로 되돌아 가게 됨
cd /d "%~dp0" : 배치파일일 실행될때 배치파일의 File 명에 해당하는 기본 환경 변수값이 %0에 할당됨.
%1은 배치 파일을 수행할때 입력한 첫번째 파라미터값, %2는 두번째, ... 등
그리고, 환경 변수에서 특정 문자열을 추출할때 ~를 사용하게 되는데,
%~d0와 같이 사용할 경우에 %0에 해당하는 파일이 있는 드라이브 문자를 알려 주게 되고,
%~p0와 같이 사용할 경우에 %0에 해당하는 파일이 있는 경로를 알려 주게 되고요.
%~dp0와 같이 사용할 경우에는 %0 파일이 있는 드라이브명과 디렉터리 경로를 알려줌.
디렉터리를 이동하는 명령인 cd 명령으로 "%~dp0"로 이동하게 되면
배치 파일이 있는 디렉터리로 작업 디렉터리를 이동하게 되겠죠.
/d 옵션은 경로만 옮기지 말고 드라이브까지 옮겨가라는 의미가 되죠.
예를 들어 C 드라이브에서 cd d:\test2라고 명령을 줬을 경우
작업 드라이브는 C에 그대로 남아 있는 상태에서 작업 경로만 d:\test2로 옮기게 되어
다시 드라이브 이동 명령을 줘야하지만 /d 옵션을 주게 됨으로 인해
작업 드라이브와 경로까지 한번에 옮겨갈 수 있게 됩니다.
이동해갈 대상 경로 앞뒤에 이중 따옴표를 사용한 이유는 경로명에 빈칸이 있을 경우에
빈칸을 포함해서 한개 경로임을 묶어 주기 위한 것이죠.
빈칸이 없는 상태의 경로라면 이중따옴표를 사용하지 않아도 되죠.
그럴 경우에는 Program Files 와 같은 명칭 중간에 빈칸이 있을 경우에 문제가 생기게 되겠죠.
이 배치 파일의 목적에 있어서는 이 명령은 굳이 사용하지 않아도 무방할거라 보여 지네요.
set "z_path=D:\test2\테스트1" : 작업 대상 파일들이 있는 경로를 지정하는 환경 변수 설정
set "z_ext=flac" : 작업 대상 파일들의 확장자를 지정하는 환경 변수 설정,
FLAC는 Free Lossless Audio Codec에 해당하는 무손실 오디오 파일에 해당하죠.
MP3가 압축을 위해 사람 귀에 영향이 적은 정보들을 제거하는 형식의 손실 압축을 하여
압축 용량을 획기적으로 줄이게 되는데, 사람 귀로는 압축 전후의 음질 변화를
잘 못느낄수 있으나 실제로는 엄청난 데이터 손실이 생기게 되는 압축 방식이죠.
즉, MP3로 한번 압축했다면 MP3 파일로는 압축 이전의 오리지날 음질 사운드 파일을
복구해 낼 수 없게 되는데, FLAC는 오리지날 음질을 그대로 유지하면서도
압축 효율이 상당히 높은 사운드 전용 압축 포멧이죠.
MP3에 해당하는 이미지 포멧이 JPG라 할 수 있고,
FLAC에 해당하는 이미지 포멧이 PNG라 할 수 있겠고요.
set "z_file=*" : 작업 대상 파일들의 파일명에 해당하는 환경 변수를 지정하는 것으로
와일드 카드인 *를 사용하여 모든 파일명을 작업 대상으로 지정하고 있죠.
:: 폴더 리스트 : 주석에 해당 하는 내용이고요. 다른 명령을 적기전에 :로 시작하면
주석으로 처리하게 되고요. rem 명령도 주석 처리지만, :를 사용하는게 장점이 많아요.
for /f "usebackq delims=" %%f in (`dir /b /ad "%z_path%"`) do ( : for 반복문에 해당하고,
/f 옵션은 in 문에서 읽은 파일 내용을 대상으로 반복 작업한다는 의미이고,
usebackq는 back quote를 사용한다는 의미이고, back quote "`"는 키보드에
좌측 상단 ~와 함께 있는 문자로 명령어를 실행용도로 사용되죠.
즉 /f 옵션에 의해 file을 찾아야 하는데, back quote를 사용하여 명령의 실행 결과를
File 내용처럼 사용한다는 의미
delims에서 지정한 문자로 문자열을 분리 시키게 되나 "delims=" 처럼 사용할 경우
한줄 전체를 구분자 분리없이 통채로 이용하겠다는 의미
%%f는 for /f in ( ) 문에 의한 첫번째 열의 값을 저장할 변수를 지정한 것이며
`dir /b /ad "%z_path%"` 는 z_path에 지정한 작업대상 디렉터리를 dir 명령으로 list하는 명령,
/b 옵션에 의해 경로 명만 표시하게 되고, /ad 옵션에 의해 파일들은 제외하고
디렉터리들만 표시하게 됨
echo "%z_path%\%%~nxf" : 대상 file명들을 표시하는 명령으로 실제 확인하는 용도이며,
실제 사용시에는 불필요한 내용
%%~nxf의 의미는 %%f가 for 문에서 사용한 반복에서 하나 하나 가져온 값들을
담는 변수가 되며 문자열에서 특정 내용을 추출하는 용도로 사용되는 ~를 붙이고
file명에 해당하는 n과 확장자를 추출하는 용도인 x 사용.
여기서 하나 하나 추출되는 내용이 file이 아닌 디렉터리명이기 때문에
x는 불필요할 것으로 보임
즉, 대상 경로에서 하위 디렉터리를 만드는 문구로 x없이
%z_path%\%%~nf"를 사용해도 될 것으로 보임
call set /a z_num=0 : 반복 횟수를 카운트 하기 위한 용도로 사용됨,
batch file에서 환경 변수가 상수로 처리되는 특성이 있기 때문에
그에 따른 문제를 해결하기 위해
call 문을 사용해서 환경 변수를 초기화 시키는 형태를 취한 것으로 보임
질문자의 요구 작업에는 불필요한 내용( 각 서브 디렉터리별로 카운트를 0부터 다시하게 됨 )
for /f "usebackq delims=" %%g in (`dir /b /s "%z_path%\%%~nxf\%z_file%.%z_ext%"`) do ( : 앞에 for문에
의해 나온 각각의 서브 디렉터리에 대해 다시 반복하기 위한 for문
앞의 for문에서 각각의 작업 대상 값을 %%f 변수에 담았고,
여기 for문에서는 %%g 변수에 각각의 대상 값을 저장하게 됨
in문 안에 dir 명령에서 /s 옵션을 주어 해당 경로 하위의
모든 파일을 하나하나 추출하는 용도로 사용되고 있음
여기서도 dir /b /s "%z_path%\%%~nf\%z_file%.%z_ext%"와 같은 형태로
x를 제거해도 무방할 것으로 보임
dir /b /s "D:\test2\테스트1\디렉터리명\*.flac" 명령이 수행되어
해당 디렉터리 하위의 모든 flac 확장자를 가진 file들의 list를 추출해냄
call set /a z_num=%%z_num%%+1 : 순번을 1씩 증가 시키는 명령,
for loop 내에 call 없이 %z_num%을 사용할 경우에
z_num 값이 loop 들어오기 전의 값으로 상수처리되는
문제가 있기 때문에 call문을 사용했고
call문을 사용했기 때문에 변수의 앞뒤에 %를 한개씩 더 붙임
질문자의 요구 작업에는 불필요한 내용
call set z_numm=00000%%z_num%% : 계산되는 값의 앞자리에 0을 5개 더 붙여서
문자열을 만듦
질문자의 요구 작업에는 불필요한 내용
call set z_numm=%%z_numm:~-4%% : 만들어진 문자열의 뒤에서 4자리만을 추출해냄,
대상 파일명을 0001~9999까지 4자리 file명으로 만들려는 목적
질문자의 요구 작업에는 불필요한 내용
call move "%%g" "%z_path%\%%~nxf\%%z_numm%%.%z_ext%" : file을 옮기는 명령
: 2번째 for문에 의해 찾아진 flac file들을
첫번째 for문에 의해 찾아진 서브 디렉터리 안에 0001.flac로 이동시키게됨
ping localhost -n 1 >nul : 예전 DOS 버전에는 sleep과 같은 명령이 없어
ping 명령으로 1초 정도 대기하게 하고 있음,
없어도 무방할 것으로 보임, 불필요하게 작업시간을 지연시키게 하는 요소가 됨
>nul 은 화면에 출력되는 내용들을 화면에 표시되지 않게 리다이렉트 시키는 용도
rd /q "%%~dpg" >nul : rd 명령은 file 및 디렉터리를 지우는 용도이며
2번째 for문에 의해 추출되어 저장되는 %%g에서 (d) 드라이브 명과 (p) 경로를 추출해냄
두번째 for문에 의해 flac file들만 추출해 내어 옮기고 나머지 남아
다른 다른 file들과 디렉터리를 제거하는 용도
) : 두번째 for 반복문의 끝
) : 첫번째 for 반복문의 끝
endlocal : setlocal의 끝을 표시
pause : 작업 마무리 후 사용자 확인을 위해 잠시 대기
오늘은 여기까지 하고 다음에 다시 질문자께서 요구하는 정리된 batch file과 실행 결과에 대한 캡쳐 화면등을 올릴 수 있도록 해 보겠습니다.
긴 시간을 내어 이렇게 다시 답변을 다는 이유는 아래 게시글과 관련이 있고요.
https://www.sharedit.co.kr/freeboards/21313
빨간신발 | 4년 이상 전
ㅇ_ㅇ 붙여넣기도 잘안되는 사이트넹...ㅋㅋㅋ
답변 달기도 힘들다..
@echo off
setlocal
cd /d %~dp0
set "z_source=.\hhhh"
cd /d "%z_source%"
for /f "usebackq delims=" %%f in (`dir /b /s /ad`) do (
echo deep-1 move "%%f\*.*" "../%%f"
echo deep-2 move "%%f\*.*" "%z_source%"
)
endlocal
pause
guest | 4년 이상 전
wansoo | 4년 이상 전
제가 직접 테스트는 안해보고 그냥 배치문 보고 바로 코멘트 적은 것 입니다.
call set /a z_num=%%z_num%%+1
call set z_numm=00000%%z_num%%
call set z_numm=%%z_numm:~-4%%
wansoo | 5년 이하 전
wansoo | 5년 이하 전
wansoo | 5년 이하 전
wansoo | 5년 이하 전
SETLOCAL enableextensions
set "folderIn=D:\test2\테스트1"
move "%folderIn%\*.*" "%~1"
ENDLOCAL
goto :eof
D: 드라이브에 \Test2\테스트1\ 파일을 만들어 Test해보니 Test2로 무브 됩니다.
기존 파일 삭제할 필요도 없구요
간단하게 이렇게 하면 되나요?
좀더 디테일하게 하려면 이렇게 ?
wansoo | 5년 이하 전
wansoo | 5년 이하 전
작동이 정말 잘 되는지 안되는지는 확인 못해 봤는데요.
질문하신분께서 작동이 잘되는데, 파일 명만 원치 않는 형태로 변경된다 하시니...
File을 복사하는 부분에서 파일 명을 변경 처리 하고 있기 때문에 해당 문제가 발생되겠고요.
파일을 복사하는 부분은 아래 쪽에서 7번째 라인 정도에 있는
call move "%%g" "%z_path%\%%~nxf\%%z_numm%%.%z_ext%"
가 되겠고요.
%%g가 해당 서버 폴더에 있는 파일 각각에 대한 전체 경로일 거 같고요.
%z_path%\%%~nxf\%%z_numm%%.%z_ext% 가 복사될 파일의 파일명 및 확장자 포함한 전체 경로가 되겠고요.
복사 대상 경로에서 File 명에 해당하는 부분만 제거해 버리면 될것으로 보이는데...
%z_path%\%%~nxf\%%z_numm%%.%z_ext% 을
%z_path%\%%~nxf\% 으로 변경하면 될거라 생각되네요.
즉,
call move "%%g" "%z_path%\%%~nxf\%%z_numm%%.%z_ext%" 부분을
call move "%%g" "%z_path%\%%~nxf\" 으로 수정하면 원하는 결과가 나올거 같아 보이네요.
이렇게 함으로 인해 불필요하게 남아 있는 코드들은 계속 남아 있긴 하겠고...
서브 폴더들에 있는 파일명이 같은 파일 들이 상위 폴더에 복사되면서 중첩되면서 파일을 오버라이트 할지 어떻게 할지에 대한 경고 메시지가 나오게 될 수도 있을 것 같고요.
깔끔하게 만들려면 시간을 가지고 다시 봐야 겠지만...
대충 봤을 경우에는
아래에서 7번째 줄 라인을
call move "%%g" "%z_path%\%%~nxf\"
으로 수정하면 되지 않을까 싶네요~