次のスクリプトは、.tex
ディレクトリ内のサフィックスを含むファイル(TeXファイルなど)を検索し、\RequireLuaTeX
そのディレクトリ内の文字列(LuaTeXファイルなど)を検索し、結果に基づいてBash配列を作成します。
latexmk
次に、配列内のファイルに対してコマンドを実行します。
配列として宣言できるカスタムファイルのリストをこの配列から除外したいと思います。
excludedfiles=(foo.tex bar.tex baz.tex)
きちんとしたアプローチについてのアドバイスを求めたいと思います。
私はすべてを配列に入れる方法が本当に好きです。まず、コマンドを実行する前にファイルのリストを簡単に一覧表示できます。しかし、私は他のアプローチも考えてみたいと思います。
#!/bin/bash
## Get LuaTeX filenames
mapfile -t -d "" filenames < <(grep -Z -rL "\RequireLuaTeX" *.tex)
## Run `latexmk` on PDFTeX files.
for filename in "${filenames[@]}"
do
base="${filename%.*}"
rm -f "$base".pdf
latexmk -pdf -shell-escape -interaction=nonstopmode "$base".tex
done
背景と説明:
TeXユーザーは私の質問に混乱する可能性があります。それで、ここで私がやろうとしていることと質問をどのように誤って書いたかを説明します。変更すると既存の回答が無効になり、混乱が生じる可能性があるので変更しません。
LaTeXファイルセットがあります。以前のバージョンはPDFLaTeXを使用していました。最新バージョンはほとんどPDFLaTeXを使用しています。 PDFLaTeXに関する質問です。私がスクリプトでやりたいことは
a) PDFLaTeX ファイルのリストを作成します。私のLuaLaTeXファイルには「\RequireLuaTeX」文字列が含まれています。したがって、この文字列を含まないファイルはPDFLaTeXファイルです。
そのため、文字列 "\RequireLuaTeX"を含まないLaTeXファイルのリストを作成しようとしています。
b)を使用してPDFLaTeXを実行しますlatexmk
。
私の質問には次のエラーがあります。私は書いた:
次のスクリプトは、
.tex
ディレクトリ内のサフィックスを含むファイル(TeXファイルなど)を検索し、\RequireLuaTeX
そのディレクトリ内の文字列(LuaTeXファイルなど)を検索し、結果に基づいてBash配列を作成します。
実際、私はこの文字列を含まないファイルが欲しいです。上記のように、これらのファイルは私のPDFLaTeXファイルに対応しているからです。
答え1
-L
パターンと一致しない Grep ファイルのリストを表示します。あなたは代わりに欲しいです-l
。さらに、Grepは単一のバックスラッシュと一致するようにデュアルバックスラッシュを確認する必要があります。
それではBashを使っているので、いくつかの便利な設定を習得しましょう。
#!/bin/bash -
shopt -s globstar extglob
mapfile -t -d "" filenames < <(grep -Zl '\\RequireLuaTeX' ./**/!(foo|bar|baz).tex)
rm -f "${filenames[@]/%.tex/.pdf}"
latexmk -pdf -shell-escape -interaction=nonstopmode "${filenames[@]}"
**/!(foo|bar|baz).tex
現在のディレクトリツリーでは、orで終わりますが、.tex
デフォルト名ではないすべてのファイルに展開されますfoo.tex
。両方bar.tex
baz.tex
globstar
そしてextglob
これに必要です。"${filenames[@]/%.tex/.pdf}"
配列内のすべての要素に展開され、各要素を置き換えます。続く.tex
合格.pdf
。
Latexmkは複数のファイルをパラメータとして提供できるため、forループをスキップできます。
答え2
を使用すると、パラメータ拡張フラグを使用してエスケープされたグローバル文字を持つ要素を連結して、配列をその要素zsh
と一致するパターンに変換できます。|
j[|]
b
#! /bin/zsh -
set -o extendedglob
excluded_file_names=(foo.tex bar.tex baz.tex)
excluded_file_names_pattern="(${(j[|])${(@b)excluded_file_names}})"
# here using the ~ extendedglob operator to apply the exclusion
tex_files=(
./**/(*.tex~$~excluded_file_names_pattern)
)
files=(
${(0)"$(grep -lZF '\RequireLuaTeX' $tex_files)"}
)
rm -f ${files/%tex/pdf}
latexmk -pdf -shell-escape -interaction=nonstopmode $files
またはあなたは使用することができますe
グローバル予選t
すべてのファイルパスが配列にあることを確認してください。
#! /bin/zsh -
excluded_file_names=(foo.tex bar.tex baz.tex)
tex_files=(
./**/*.tex(^e['(($excluded_file_names[(Ie)$REPLY:t]))'])
)
files=(
${(0)"$(grep -lZF '\RequireLuaTeX' $tex_files)"}
)
rm -f ${files/%tex/pdf}
latexmk -pdf -shell-escape -interaction=nonstopmode $files
答え3
この種の問題を解決する方法は、検索なしで即時検索を介してファイル名/パターンリストをハッシュに変換することです。 (銀パターンexcludedFiles
のようにz*.tex
z*.tex
excludedFiles
# User configurable list of files and patterns
excludedFiles=(foo.tex bar.tex baz.tex z*.tex)
# Convert the list into a hash
declare -A excludedHash
for excludedFile in "${excludedFiles[@]}"
do
[[ -e "$excludedFile" ]] && excludedHash[$excludedFile]=yes
done
# Processing
for filename in "${filenames[@]}"
do
[[ -n "${excludedHash[$filename]}" ]] && continue # Skip if filename is in hash
base="${filename%.*}"
rm -f "$base".pdf
latexmk -pdf -shell-escape -interaction=nonstopmode "$base".tex
done
答え4
配列なしで単純なforループを使用することをお勧めします。
excludedfiles="foo.tex|bar.tex|baz.tex"
for i in $(ls *.tex | egrep -vx ${excludedfiles});do
filename=$(grep -H "\\RequireLuaTeX" $i | awk -F ':' '{print $1}')
base=${filename%.*}
if [[ "$base" == "" ]];then continue; fi
rm -f "$base".pdf
latexmk -pdf -shell-escape -interaction=nonstopmode "$base".tex
done
できること:
- ファイルを探す
.tex
- 指定されたファイルフィルタリング(egrep)
- テキスト検索はパターンを指定します
\RequireLuaTeX
(検索時に「\\」には\が含まれます)。 - 空の変数をチェックして空
filename
の場合は、次の変数に移動します(grepが一致するものが見つからない場合に発生します)。 - 与えられたコマンドで完了
rm
Finalとcommandなしでスクリプトをテストし、latex
「エコー」して出力を確認することをお勧めします"$base"
。 (すべての解決策について)ファイル名の空白の問題を想像できます。
...
if [[ "$base" == "" ]];then continue; fi
echo $base
done
必要に応じて、すべての検索パターンを抽出して、より良い調整と簡単な処理のために変数に入れることができます。