상세 컨텐츠

본문 제목

파일의 상대 경로 출력하기

MS Batch

by techbard 2022. 2. 7. 15:14

본문

반응형

업무적으로 검증한 결과를 jpg 파일로 떨구고 있는데 이 파일이 연속성을 가져야 의미가 있고 한 눈에 확인하기 위해 jpg 파일을 index.html로 생성해 웹 브라우저를 통해 확인하고 있다. (웹 브라우저는 모든 PC에 설치되어 있을 테니까)

 

처음에는 jpg 파일의 절대 경로를 생성해서 index.html 에서 참조하도록 만들었는데 이 파일들을 다른 사람에게 공유할 때 상위 경로 폴더 명이 달라지는 경우 index.html 파일에서 참조를 하지 못하는 상황이 발생했다. 즉 내 PC의 폴더 구조에서 생성한 index.html 과 JPG는 다른 위치에 복사하는 경우 참조가 끊어지는 것이다.

 

이를 해결하기 위해서는 html에 절대 경로로 참조하고 있는 부분을 상대 경로로 바꿔야 하는데 여러 가지 구현법을 생각해 볼 수 있다.

 

  1. dir로 얻은 절대 경로에서 문자열 파싱을 해서 원하는 부분만 잘라낸다.
  2. 상대 경로를 출력해 주는 윈도우 내부 프로그램을 이용한다.

 

MS batch에서는 문자열 파싱이 그다지 강력하지 않고 이 부분에서 많은 실수를 수정해야 하므로 선택하지 않는다. 그래서 파일을 대상으로 원하는 추가 동작을 지정할 수 있는 윈도우 내장 프로그램을 찾아 봤는데 이것이 매우 적당하다.

FORFILES [/P pathname] [/M searchmask] [/S]
         [/C command] [/D [+ | -] {yyyy-MM-dd | dd}]

설명:
    파일(또는 파일 집합)을 선택하고 파일에 명령을
    실행합니다. 일괄 작업에 유용합니다.

매개 변수 목록:
    /P    pathname      검색을 시작할 경로를 지정합니다.
                        현재 작업 디렉터리(.)가 기본
                        폴더입니다.

    /M    searchmask    검색 마스크에 따라 파일을 검색합니다.
                        '*'이 기본 검색 마스크입니다.

    /S                  하위 폴더를 포함하도록
                        지정합니다. 예, "DIR /S"

    /C    command       각 파일에 실행할 명령을 지정합니다.
                        명령 문자열을 큰따옴표로 묶어야
                        합니다.

그동안 수 십년간 원시적인 작업에만 동원이 되었던 윈도우 내장 프로그램 중에 그나마 복잡한 작업을 처리한다. 사용법은 검색을 하거나 도움말을 보고 따라 하면 되니 생략하고 이것을 가지고 어떻게 대상 파일의 상대 경로를 추출하는지 설명하겠다.

 

forfiles의 도움말을 보면 /C 옵션에 다음과 같은 설명이 있다.

  /C    command       각 파일에 실행할 명령을 지정합니다.
                        명령 문자열을 큰따옴표로 묶어야
                        합니다.

                        "cmd /c echo @file"이 기본 명령입니다.

                        명령 문자열에 다음 변수를 사용할 수
                        있습니다.
                        @file    - 파일 이름을 반환합니다.
                        @fname   - 확장명 없이 파일 이름을
                                   반환합니다.
                        @ext     - 파일의 확장명만
                                   반환합니다.
                        @path    - 파일의 전체 경로를 반환합니다.
                        @relpath - 파일의 상대 경로를
                                   반환합니다.

이것을 시험해 보면

forfiles /P . /S /M *.jpg /C "cmd /c echo @relpath"

".\2022-02-07-12-02-07.jpg"
".\2022-02-07-12-01-56.jpg"

즉 현재 폴더 하위까지 포함해 jpg 확장자를 가지는 파일의 상대 경로를 출력함을 알 수 있다.

 

forfiles가 상당히 강력한데 대상이 되는 파일에 대한 2차적인 처리를 지정할 수 있다는 것이다. /C 뒤에 명령어에 부합하기만 하면 어떤 2차 처리도 가능하게 되는 것으로 무한한 응용이 가능하며 세부 옵션인 @relpath 를 주어 대상 파일들의 상대 경로를 얻었다.

 

추가...

 

스택오버플로에서 소스를 보고 훨씬 간단하다 싶어 바꿔보고 잘 되어서 다시 기록을 한다.

https://stackoverflow.com/questions/57841792/how-do-i-get-a-relative-path-out-of-a-windows-batch-file-using-echo

 

How do I get a relative path out of a windows batch file using echo?

How do I get relative directories / partial paths to display as echo output from a windows .bat file? How to split the filename from a full path in batch? Talks about everything but. I've found ...

stackoverflow.com

위에 forfiles 버전은 forfiles가 필터링해서 출력하는 파일 입력이 마스킹 밖에는 되지 않아 이걸 생성시간 순서로 상대 경로를 얻으려면 일일이 파일명을 던져 주어야 한다. 나는 무식하게 두 번의 for 문을 통해 한 번은 순수 파일 이름을 얻어 그것을 또 다시 forfiles에 던져 forfiles는 하위 경로 탐색을 통해 뒤져 찾으면 다시 /C 옵션으로 2차로 CMD를 띄운 후 상대 경로를 출력하는 아주 해괴망칙한 방법을 쓰고 있었다.
그런데 위의 제안자는 그냥 얻어 낸 절대 경로에서 현재 경로를 리턴하는 %CD% 변수를 문자열 치환으로 없애 버림으로써 상대 경로를 얻고 있다. 당연히 내가 억지로 구현한 것보다는 훨씬 간단하고 파일 액세스도 적다.
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "delims=*" %%R in (jpglist.txt) do (
    set relpath=%%R
    set relpath="!relpath:%cd%\=.\!"
    echo     ^<a href=!relpath!  target="_blank"^>^<img src=!relpath!/^>^</a^> >> index.html
)
SETLOCAL DISABLEDELAYEDEXPANSION

결국 위와 같은 형태로 구현이 가능하였다. 이미 jpglist.txt에는 dir 커맨드에 적절한 옵션을 주어 생성시간 순으로 정렬된 전체 경로가 들어가 있고 그 파일을 순서대로 읽어 그 중에서 %CD% 경로를 제거하고 앞에 . (current directory)를 추가함으로써 해당 파일 경로에 대한 상대 경로명 얻기가 되었다.

 

추가로 Win Batch에서는 for 문에서 회돌이하며 변수를 사용할 때 지연 확장 (delayed expansion) 이라는 추가문을 명시하지 않으면 시작 시점에 변수가 고정이 되므로 회돌이 결과가 제대로 나오지 않는다. 또한 지연 확장을 사용하는 경우 변수를 사용이 %변수명% 에서 !변수명! 으로 변경해 사용해야 한다고 한다.

반응형

관련글 더보기

댓글 영역