ワイルドカードを使用して何千ものepubファイルをmobiにエレガントに変換する

ワイルドカードを使用して何千ものepubファイルをmobiにエレガントに変換する

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

Zshはこのループのよりエレガントなフォーマットをサポートしています。

ファイル名にスペース文字が含まれておらず、通常Makeとシェルで安全に処理できる場合は、シェルスクリプトの代わりにGNU Makeを使用できますMakefile

all: $(patsubst %.epub,%.mobi,$(wildcard *.epub))

%.mobi : %.epub
        ebook-convert ./$< ./$@

その後、実行すると、makeすべての.epubファイルが1つのファイルに変換されます.mobi。ファイルを更新するために、必要に応じてこのコマンドを繰り返し実行できます。このコマンドは、欠落しているファイルまたはソースファイルより古いファイルのみをビルドします。 (ebook-convert行が空白ではなくタブで始まることを確認してください。)

答え2

シェルを含むzsh:

for f (./*.epub) ebook-convert $f $f:r.mobi

/など、$f:rルート名(拡張子のない部分)に拡張されます。$fcshvim

または:

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@zargsebook-convert@

ebook-convertacceptコマンドが呼び出されたら、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.mobieval 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)が各ファイルを取得します。ファイルを1つの別々の引数として保存します。

したがって、 と を含むフォルダが与えられると、シェルは呼び出される項目a.epub(b.epubここfile with spaces.epub) に対する 3 つの別々の引数*.epuba.epubb.epubと に拡張されます。file with spaces.epubebook-convert

同じフォルダが与えられた場合、一致*.mobiするものがないため、ebook-convertリテラル引数を受け取ります*.mobiebook-convert観点から見ると、3つのepubファイルのリストと存在しない1つのmobiファイルのリストを取得します。引数リストで行うことはこれに依存します(引数が多すぎると文句を言うか、各ファイルを追加しようとしていると思います)。順番に)epubは文字通り「*.mobi」という名前のmobiファイルに変換されます。

プログラム(または組み込みシェル、関数、またはスクリプトなど)がファイル名であると予想していますが、globを含む引数を処理する方法についてのグローバルな保証はありません。通常、引数は文字列リテラルとして扱われ、存在しないかの*.mobiように反応しanything_else.mobiますが、このようなことが起こらなければならないという法的要件はありません。

たとえば、他のグローブでも同様です。は?.epub含まれますが、含まれていません。a.epubb.epubfile with spaces.epub

他の方々が指摘したように、できるglobを使用してループ駆動 -for file in *.epub ; do ...スペースを処理するには、「file」への参照が必要であることに注意してください。ワイルドカードはループ自体の単一引数であることをfor file in *.epub保証するだけであり、ループ本体には拡張されません(3つの個別のパラメータなど)。 :、および)について。file with spaces.epubforfor file in *.epub ; do ebook-convert $filefile with spaces.epubfilewithspaces.epub

これはすべてglob文字を必要とするプログラムの引数を引用する必要がある理由です。これにより、シェルがglobを拡張するのを防ぎ、実際に呼び出されたプログラムがユーザーが作成した引数を見ることができます。たとえば、find . -type f -name '*.epub'このディレクトリとすべてのサブディレクトリにあるすべてのepubファイルを見つけて名前を印刷します。引数としてfind . -type f -name *.epub見ることができますが、どうすればいいかわからないため、エラーが発生します。b.epubfile 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

*とにかく、Unixシェルでは非常に明確な意味を持っているので、他のものを使用する必要があります。

関連情報