GNU의 재귀 와일드 카드는?
을 (를) 사용 make
한지 오래 되었으니 참아주세요 ...
flac
.FLAC 파일이 포함 된 디렉토리가 있습니다. mp3
MP3 파일이 포함 된 해당 디렉토리가 있습니다. FLAC 파일이 해당 MP3 파일보다 새로운 경우 (또는 해당 MP3 파일이 존재하지 않음) FLAC 파일을 MP3 파일로 변환하고 태그를 복사하는 명령을 실행하고 싶습니다.
키커 : flac
디렉터리를 재귀 적 으로 검색하고 디렉터리에 해당 하위 디렉터리를 만들어야합니다 mp3
. 디렉토리와 파일은 이름에 공백이있을 수 있으며 UTF-8로 이름이 지정됩니다.
그리고 나는 make
이것을 운전하는 데 사용하고 싶습니다 .
이 라인을 따라 뭔가를 시도 할 것입니다
FLAC_FILES = $(shell find flac/ -type f -name '*.flac')
MP3_FILES = $(patsubst flac/%.flac, mp3/%.mp3, $(FLAC_FILES))
.PHONY: all
all: $(MP3_FILES)
mp3/%.mp3: flac/%.flac
@mkdir -p "$(@D)"
@echo convert "$<" to "$@"
make
초보자 를 위한 몇 가지 간단한 참고 사항 :
@
명령의 방지 앞에make
실제로 그것을 실행하기 전에 명령을 인쇄에서.$(@D)
대상 파일 이름 ($@
) 의 디렉토리 부분입니다.- 쉘 명령이있는 행이 공백이 아닌 탭으로 시작하는지 확인하십시오.
이것이 모든 UTF-8 문자 및 항목을 처리해야한다고해도 파일 또는 디렉토리 이름의 공백에서 실패 make
합니다. 공백을 사용하여 메이크 파일에서 항목을 분리하고이를 해결하는 방법을 모릅니다. 그래서 쉘 스크립트 만 남았습니다. 두렵습니다. :-/
다음과 같이 고유 한 재귀 와일드 카드 함수를 정의 할 수 있습니다.
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
첫 번째 매개 변수 ( $1
)는 디렉토리 이름이고 두 번째 매개 변수 ( )는 $2
일치시킬 패턴입니다.
예
현재 디렉토리에서 모든 C 파일을 찾으려면 :
$(call rwildcard, , *.c)
모든 .c
및 .h
파일 을 찾으려면 다음 을 수행 하십시오 src
.
$(call rwildcard, src/, *.c *.h)
FWIW, Makefile 에서 다음과 같은 것을 사용했습니다 .
RECURSIVE_MANIFEST = `find . -type f -print`
위의 예는 현재 디렉토리 ( '.' )에서 모든 "일반 파일"( '-type f' )을 검색하고 RECURSIVE_MANIFEST
찾은 모든 파일에 make 변수를 설정합니다 . 그런 다음 패턴 대체를 사용하여이 목록을 줄이거 나, 또는 더 많은 인수를 find에 제공 하여 반환되는 항목을 좁힐 수 있습니다. find 는 man 페이지를 참조하십시오 .
내 솔루션은 위의 것을 기반으로하며 sed
대신 공백을 이스케이프하고 patsubst
출력을 엉망으로 사용 find
합니다.
flac /에서 ogg /로 이동
OGGS = $(shell find flac -type f -name "*.flac" | sed 's/ /\\ /g;s/flac\//ogg\//;s/\.flac/\.ogg/' )
주의 사항 :
- 파일 이름에 세미콜론이 있으면 여전히 소리가 나지만 매우 드뭅니다.
- $ (@ D) 트릭은 작동하지 않지만 (무의미한 출력) oggenc는 사용자를 위해 디렉토리를 생성합니다!
다음은 원래 문제를 해결하기 위해 빠르게 해킹 한 Python 스크립트입니다. 음악 라이브러리의 압축 된 사본을 보관하세요. AAC 파일이 이미 존재하고 ALAC 파일보다 최신 버전이 아닌 경우 스크립트는 .m4a 파일 (ALAC로 가정)을 AAC 형식으로 변환합니다. 라이브러리의 MP3 파일은 이미 압축되어 있으므로 링크됩니다.
스크립트 ( ctrl-c) 를 중단하면 반 변환 된 파일이 남게됩니다.
나는 원래 이것을 처리하기 위해 Makefile을 작성하고 싶었지만 파일 이름의 공백을 처리 할 수 없기 때문에 (허용되는 답변 참조) bash 스크립트를 작성하면 고통의 세계에 빠질 수 있으므로 Python은 그렇습니다. 매우 간단하고 짧기 때문에 필요에 맞게 쉽게 조정할 수 있습니다.
from __future__ import print_function
import glob
import os
import subprocess
UNCOMPRESSED_DIR = 'Music'
COMPRESSED = 'compressed_'
UNCOMPRESSED_EXTS = ('m4a', ) # files to convert to lossy format
LINK_EXTS = ('mp3', ) # files to link instead of convert
for root, dirs, files in os.walk(UNCOMPRESSED_DIR):
out_root = COMPRESSED + root
if not os.path.exists(out_root):
os.mkdir(out_root)
for file in files:
file_path = os.path.join(root, file)
file_root, ext = os.path.splitext(file_path)
if ext[1:] in LINK_EXTS:
if not os.path.exists(COMPRESSED + file_path):
print('Linking {}'.format(file_path))
link_source = os.path.relpath(file_path, out_root)
os.symlink(link_source, COMPRESSED + file_path)
continue
if ext[1:] not in UNCOMPRESSED_EXTS:
print('Skipping {}'.format(file_path))
continue
out_file_path = COMPRESSED + file_path
if (os.path.exists(out_file_path)
and os.path.getctime(out_file_path) > os.path.getctime(file_path)):
print('Up to date: {}'.format(file_path))
continue
print('Converting {}'.format(file_path))
subprocess.call(['ffmpeg', '-y', '-i', file_path,
'-c:a', 'libfdk_aac', '-vbr', '4',
out_file_path])
물론 이것은 인코딩을 병렬로 수행하도록 향상 될 수 있습니다. 그것은 독자에게 연습으로 남겨집니다 ;-)
Bash 4.x를 사용 하는 경우 새 globbing 옵션을 사용할 수 있습니다 . 예를 들면 다음과 같습니다.
SHELL:=/bin/bash -O globstar
list:
@echo Flac: $(shell ls flac/**/*.flac)
@echo MP3: $(shell ls mp3/**/*.mp3)
이러한 종류의 재귀 와일드 카드는 관심있는 모든 파일 ( .flac , .mp3 등 )을 찾을 수 있습니다 . 영형
참고 URL : https://stackoverflow.com/questions/2483182/recursive-wildcards-in-gnu-make
'program story' 카테고리의 다른 글
Swift에서 일반 프로토콜을 만드는 방법은 무엇입니까? (0) | 2020.10.05 |
---|---|
jQuery를 사용하여 너비를 백분율로 설정 (0) | 2020.10.05 |
intellij 아이디어 실행 구성 백업 (0) | 2020.10.05 |
IF… 또는 IF… Windows 배치 파일에서 (0) | 2020.10.05 |
Google App Engine의 자바 용 JDO와 JPA (0) | 2020.10.05 |