@echo off
SETLOCAL EnableDelayedExpansion
FOR /R %%E IN (3rdparty/include/*.h) DO (
set full_path=%%E
set file=%%~nxE
echo !full_path!
echo !file!
)
기본적으로 %%E
에는 full_path가 들어가 있다.
%%~nE
는 순수한 파일명만 뽑아내고
%%~nxE
는 확장자를 포함한 파일명만 추출한다.
또한 for문 내부에서 변수를 사용하려면 앞의 SETLOCAL ENABLEDELAYEDEXPANSION를 사용해야 한다.
한줄 주석은 ::
으로 시작한다. 다중 주석은 goto 문으로 해결한다.
::This is comment
goto COMMENT
::looks like multiline comment
:COMMENT
@echo off
setlocal EnableDelayedExpansion
set LF=^
::반드시 두줄 띄워야 함
set "content="
for /f "delims=" %%x in (file.txt) do (
set "content=!content!%%x!LF!"
)
echo !content!
endlocal
set /p "content="<"file.txt"
set idx=0
set /A idx=idx+1
@echo off
setlocal EnableDelayedExpansion
set list=
FOR /L %%i in (0,1,10) do (
set list[%%i]=%%i
)
echo ----
FOR /L %%i in (0,1,10) do (
echo !list[%%i]!
)
endlocal
setlocal ENABLEDELAYEDEXPANSION
set word=table
set str="jump over the chair"
set str=%str:chair=!word!%
배열을 !로 감싸야 하는 환경에서 인덱스 까지 !로 감쌀순 없다.
이때 함수호출을 이용해 대신 쓸수 있다.
@echo off
setlocal EnableDelayedExpansion
FOR /L %%i in (0,1,10) do (
set list[%%i]=##%%i##
)
set idx=0
echo ----
FOR /L %%i in (0,1,10) do (
echo Element : !list[%%i]!
set /A idx=!idx!+1
call :FOO !idx!
)
endlocal
:FOO
echo !list[%1]!
powershell "(New-Object System.Net.WebClient).DownloadFile('http://url.sample','filename.sample')"
가능하다면 curl 을 쓰는것이 좋다. 대용량의 파일의 경우에는 위의 방법이 실패할 수 도 있다.
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('foo.zip', 'bar'); }"
IF EXIST "folder" (
RMDIR /S /Q "folder"
)
IF EXIST "file" (
DEL "file"
)
call other.bat
call 을 쓰지 않으면 배치파일이 실행한 배치파일로 대치되어 밑에 구문들이 실행되지 않는다.
call :SafeDEL "*.pdb"
call :SafeRMDIR "x64"
exit /b
:SafeDEL
IF EXIST "%~1" (
DEL "%~1"
)
exit /b
:SafeRMDIR
IF EXIST "%~1" (
RMDIR /S /Q "%~1"
)
exit /b
위와 같은 간단한 방법으로 함수를 만들수 있다.
xcopy /Y "a\*.exe" "b\"
중요한 점은 경로에 slash 를 쓰면 안되고 back-slash 를 써야 한다.
slash는 옵션에서 사용되기 때문인것 같다.
/Y 는 덮어쓰기 허용 옵션이다.
xcopy /d /i /Y "a\*.exe" "b\"
/d /i 옵션은 이미 존재하는 파일인 경우 건너뛴다는 옵션이다.
아래 코드를 첫부분에 넣어주면 UAC를 띄우고 관리자 권한을 얻는다.
@echo off
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (
echo Get admin permission...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
set params = %*:"=""
echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
rem del "%temp%\getadmin.vbs"
exit /B
:gotAdmin
pushd "%CD%"
CD /D "%~dp0"
%NUMBER_OF_PROCESSORS%
timeout /t 5 /nobreak > NUL
5초를 대기하는 코드 이다.
powershell "$HTML=Invoke-WebRequest -Uri 'https://www.google.co.kr/';($HTML.ParsedHtml.getElementsByTagName('a') | %% href) > parse.txt"
위는 모든 a태그의 href를 출력하는 명령어이다.
powershell "get-content parse.txt -ReadCount 1000 | foreach { $_ -match 'abcd' } | out-file -encoding ascii link.txt"
텍스트파일에서 abcd가 있는 줄만 따로 출력하는 명령어 이다.
이 문제가 발생할땐 아래의 구문을 실행한뒤, 웹 모듈을 실행하여야 한다.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
:GetFileSize
set FILESIZE=%~z1
exit /b
call :GetFileSize "README.md"
echo %FILESIZE%
함수로 작성하여만 한다. 함수 내부에서 %~z1 을 환경변수에 넣고, 함수 호출한뒤 그 값을 사용하는 방식이다.
https://code.i-harness.com/ko/q/124e1d
call :FONT "BMYEONSUNG_ttf.ttf"
exit /b
:FONT
SET FFILE=%~n1%~x1
SET FNAME=%~n1
SET FNAME=%FNAME:-= %
IF "%~x1"==".otf" SET FTYPE=(OpenType)
IF "%~x1"==".ttf" SET FTYPE=(TrueType)
COPY /Y "%~n1%~x1" "%SystemRoot%\Fonts\" >nul
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /v "%FNAME% %FTYPE%" /t REG_SZ /d "%FFILE%" /f >nul
exit /b
COMMAND >nul 2>&1
뒤에 >nul 2>&1
을 붙여 주면 된다.
:ProgramExistInit
set PEI=0
exit /b
:ProgramExistTest
where %~1 >nul 2>&1
set /a PEI=%PEI%+%ERRORLEVEL%
exit /b
위와 같은 함수를 정의 하고 아래와 같이 테스트 한다.
call :ProgramExistInit
call :ProgramExistTest python
call :ProgramExistTest cmake
call :ProgramExistTest git
if %PEI% EQU 0 (
echo Program exist
)
cd 명령어는 기본적으로 드라이브가 다르면 이동하지 않는다. /D 옵션으로 드라이브를 이동할 수 있다.
cd /D %TEMP%
echo %~dp0 <전체 경로>
echo %~n0 <확장자를 제외한 파일 이름>
echo %~x0 <확장자>
echo %~nx0 <확장자를 포함한 파일 이름>
아래 예시는 nvcc의 위치를 출력하고 변수로 가져오는 방법이다.
set /p
구문에서 문자열로 감싼 범위를 주의해야 한다.
where nvcc > "%temp%\cudapath.txt"
set /p "cudapath="<"%TEMP%\cudapath.txt"
adb devices | grep %android_device% > %TEMP%\%~n0.tmp
for %%A in ("%TEMP%\%~n0.tmp") do (
if %%~zA EQU 0 (
echo Device is not attatched!
pause
exit /b
)
)
powershell의 write-host를 쓰는게 제일 편하다.
@echo off
powershell write-host -fore Cyan hello, world
powershell write-host -back Red where is comma
powershell write-host -fore Green -back Red Green on Red
아래처름 %time%
은 hour가 1자리일 때 공백이 생기는 문제와 :
는 파일명으로 사용할 수 없는 문자여서 slicing과 replace를 사용하여 처리한다.
#echo %date%
2023-06-24
#echo %time%
0:53:11.74
set CTIME=%time: =0%
echo %DATE:~0,4%%DATE:~5,2%%DATE:~8,2%_%CTIME:~0,2%%CTIME:~3,2%%CTIME:~6,2%.mp4
# 20230624_005443.mp4
임시폴더에 시간 변수를 포함하여 가능한 겹치지 않는 임시파일을 만드는 방법.
출력 예시: C:\Users\spring\AppData\Local\Temp\20240518-125039.txt
set "extension=.txt"
set "datetime=%date:~0,4%%date:~5,2%%date:~8,2%-%time:~0,2%%time:~3,2%%time:~6,2%"
set "datetime=%datetime: =0%"
set "datetime=%datetime::=-%"
set "datetime=%datetime:.=%"
set "temp_file=%TEMP%\%datetime%%extension%"
echo %temp_file%