![와일드카드를 사용하여 수천 개의 epub 파일을 mobi로 우아하게 변환](https://linux55.com/image/195805/%EC%99%80%EC%9D%BC%EB%93%9C%EC%B9%B4%EB%93%9C%EB%A5%BC%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20%EC%88%98%EC%B2%9C%20%EA%B0%9C%EC%9D%98%20epub%20%ED%8C%8C%EC%9D%BC%EC%9D%84%20mobi%EB%A1%9C%20%EC%9A%B0%EC%95%84%ED%95%98%EA%B2%8C%20%EB%B3%80%ED%99%98.png)
1000개의 파일에 대해 다음 명령을 실행하고 있습니다.
ebook-convert <name-of-first-file>.epub <name-of-first-file>.mobi
ebook-convert <name-of-second-file>.epub <name-of-second-file>.mobi
분명히, 1000개의 파일에 대해 이 작업을 수동으로 수행하는 대신 이 작업에 대한 bash 스크립트를 작성할 수 있습니다.
Linux에서 이와 같은 작업을 수행하는 더 쉬운 방법이 있는지 궁금합니다.
ebook-convert *.epub *.mobi
위 시나리오에 적용되는 것과 유사한 방식으로 와일드카드를 사용할 수 있습니까?
답변1
와일드카드를 사용하여 이 작업을 직접 수행할 수는 없지만 for
루프를 사용할 수 있습니다.
for epub in ./*.epub; do ebook-convert "${epub}" "${epub%.epub}.mobi"; done
파일 이름에 공백 문자가 포함되어 있지 않고 일반적으로 Make와 셸에서 안전하게 처리할 수 있는 경우 셸 스크립트 대신 GNU Make를 사용할 수 있습니다 Makefile
.
all: $(patsubst %.epub,%.mobi,$(wildcard *.epub))
%.mobi : %.epub
ebook-convert ./$< ./$@
그런 다음 를 실행하면 make
모든 .epub
파일이 하나의 파일로 변환됩니다 .mobi
. 파일을 업데이트하기 위해 필요에 따라 이 명령을 반복적으로 실행할 수 있습니다. 이 명령은 누락되었거나 소스 파일보다 오래된 파일만 빌드합니다. ( ebook-convert
줄이 공백이 아닌 탭으로 시작하는지 확인하세요 .)
답변2
쉘 포함 zsh
:
for f (./*.epub) ebook-convert $f $f:r.mobi
/ 와 같이 $f:r
루트 이름(확장자가 없는 부분)으로 확장됩니다 .$f
csh
vim
또는:
autoload -Uz zmv # best in ~/.zshrc
zmv -P ebook-convert './(*).epub' './$1.mobi`
( 옵션 구분자가 ebook-convert
인식되지 않는 것 같아서 로 시작하는 파일 이름을 처리할 수 있는 대신 접두사를 사용 하고 사용해야 합니다 )--
./
-P
-p
-
zmv
주로 대량 이름 바꾸기에 사용되지만 / 를 사용한 대량 복사/링크에도 사용되거나 -C
프로그램 -L
이 -p
/ 를 사용하도록 지정하여 모든 형태의 변경/변환으로 확장될 수 있습니다 -P
.
또는:
autoload -Uz zmv
alias ebc='noglob zmv -WP ebook-convert'
ebc ./*.epub ./*.mobi
-W
, 를 사용하여 zmv
소스 패턴의 모든 와일드카드를 캡처하고 교체 시 증분 등을 사용하여 ${1}
모든 와일드카드를 변환합니다. ${2}
.zmv -W './*.epub' './*.mobi'
zmv -W './(*).epub' './${1}.mobi'
noglob
인용을 방지하려면 명령 매개변수에서 와일드카드를 비활성화하십시오.
또는:
autoload -Uz zargs # best in ~/.zshrc
zargs -I@ ./*.epub(:r) -- ebook-convert @.epub @.mobi
zargs
매개변수 목록을 일괄 처리 하는 zsh
것과 유사한 명령입니다. 파일의 루트 이름을 가져온 다음 실행 명령줄을 사용하여 각 루트 이름을 각 파일의 루트 이름으로 차례로 바꿉니다.xargs
./*.epub(:r)
.epub
-I@
zargs
ebook-convert
@
ebook-convert
accept 명령이 호출 되면 ebook-convert file1.epub file1.mobi file2.epub file2.mobi ...
다음을 수행할 수도 있습니다.
ebook-convert ./*.epub(e['reply=($REPLY $REPLY:r.mobi)'])
./file1.epub
./file1.mobi
./file2.epub
./file2.mobi
e
val glob 한정자는 일치하는 각 파일에 대해 제공된 코드를 실행하므로 glob은...으로 확장됩니다. 여기서 설정은 glob $reply
이 확장되어야 하는 인수 목록을 정의합니다.
또는:
(){epub-convert $^@.{epub,mobi};} ./*.epub(:r)
파일 루트 이름 목록을 .epub
익명 함수에 전달합니다. 이 함수는 중괄호 확장을 사용하여 인수 .epub
와 .mobi
추가 인수를 전달합니다.
이 모든 것에서 *.epub
아직 새로운 대응 항목이 없는 .mobi
파일 로 glob 확장을 제한하려면 e['[[ ! $REPLY:r.mobi -nt $REPLY ]]']
glob 한정자를 추가하거나 루프의 일부로 검사를 추가할 수 있습니다.
for epub (./*.epub) {
mobi=$epub:r.mobi
[[ $mobi -nt $epub ]] || ebook-convert $epub $mobi
}
답변3
위 시나리오에 적용되는 것과 유사한 방식으로 와일드카드를 사용할 수 있습니까?
ebook-convert *epub *mobi
와일드카드(실제 "쉘 와일드카드")가 작동하는 방식 때문에 그렇지 않습니다 . 그러나 와일드카드로 시작할 수 있습니다.
개념적으로 쉘 와일드카드는 매우 간단합니다. 해당 와일드카드와 일치하는 모든 파일을 찾아 해당 와일드카드를 해당 파일 목록으로 바꾸고 공백 및 기타 "특수" 문자를 처리하여 호출되는 작업(일반적으로 프로그램, 여기서는 ebook-convert
)이 각 파일을 가져오도록 합니다. 파일을 하나의 별도 인수로 저장합니다.
따라서 , 및 가 포함된 폴더가 주어지면 a.epub
쉘 b.epub
은 file with spaces.epub
호출 되는 항목(여기 ) 에 대한 3개의 별도 인수 *.epub
로 a.epub
, b.epub
및 로 확장됩니다.file with spaces.epub
ebook-convert
동일한 폴더가 주어지면 *.mobi
일치하는 항목이 없으므로 ebook-convert
리터럴 인수가 수신됩니다 *.mobi
. ebook-convert
관점 에서 볼 때, 3개의 epub 파일 목록과 존재하지 않는 1개의 mobi 파일 목록을 얻습니다. 인수 목록으로 수행하는 작업은 이에 따라 다릅니다(인수가 너무 많다고 불평하거나 각 파일을 추가하려고 시도하는 것으로 추측됩니다). 차례로) epub는 말 그대로 "*.mobi"라는 이름의 mobi 파일로 변환됩니다.
프로그램(또는 내장 셸, 함수 또는 스크립트 등)이 파일 이름일 것으로 예상하지만 glob을 포함하는 인수를 처리하는 방법에 대한 전역적인 보장은 없습니다. 일반적으로 인수는 문자열 리터럴로 처리되어 존재하지 않는 *.mobi
것처럼 반응 anything_else.mobi
하지만, 이러한 일이 발생해야 한다는 법적 요구 사항은 없습니다.
예를 들어 다른 글로브에서도 마찬가지입니다. 은 ?.epub
포함되지만 은 포함되지 않습니다 .a.epub
b.epub
file with spaces.epub
다른 분들이 지적하셨듯이,할 수 있는glob을 사용하여 루프 구동 - for file in *.epub ; do ...
공백을 처리하려면 "file"에 대한 참조가 필요하다는 점에 유의하세요. 와일드카드는 루프 자체에 대한 단일 인수임을 for file in *.epub
보장할 뿐이며 루프 본문으로 확장되지는 않습니다(예: 세 개의 개별 매개변수) . : , 및 ) 에 대해 .file with spaces.epub
for
for file in *.epub ; do ebook-convert $file
file with spaces.epub
file
with
spaces.epub
이 모든 것이 glob 문자가 필요한 프로그램에 대해 인수를 인용해야 하는 이유이기도 합니다. 이렇게 하면 쉘이 glob을 확장하는 것을 방지하고 실제로 호출된 프로그램이 사용자가 작성한 인수를 볼 수 있습니다. 예를 들어, find . -type f -name '*.epub'
이 디렉토리와 모든 하위 디렉토리에 있는 모든 epub 파일을 찾아서 이름을 인쇄합니다. 및 인수로 find . -type f -name *.epub
볼 수 있지만 어떻게 해야 할지 모르기 때문에 오류가 발생합니다.b.epub
file with spaces.epub
답변4
%.mobi: %.epub
나는 GNU make와 파일 이름 제한 없이 약간의 래퍼를 사용하여 GNU make에서 허용되는 귀여운 답변과 같은 작업을 수행할 수 있다고 생각합니다 .
from_to(){
sp=${1%%%*}; ss=${1#*%}; shift
dp=${1%%%*}; ds=${1#*%}; shift
for s in "$sp"*"$ss"; do
d=${s#"$sp"}; d=$dp${d%"$ss"}$ds
"$@" "$s" "$d" || exit 1
done
}
다음과 같이 사용할 수 있습니다.
from_to %.epub %.mobi ebook-convert
from_to dir1/book_%.epub dir2/%.mobi ebook-convert
모의 테스트 예:
% touch {1,2,3}.foo
% from_to ./%.foo bar/%.baz echo translate --
translate -- ./1.foo bar/1.baz
translate -- ./2.foo bar/2.baz
translate -- ./3.foo bar/3.baz
*
어쨌든, 유닉스 쉘에서는 매우 명확한 의미를 갖고 있기 때문에 다른 것을 사용해야 합니다 .