特定のファイルのリストを除いて、ファイル名がパターンと一致するファイルに対してコマンドを実行します。

特定のファイルのリストを除いて、ファイル名がパターンと一致するファイルに対してコマンドを実行します。

次のスクリプトは、.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.texbaz.texglobstarそして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*.texz*.texexcludedFiles

# 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

できること:

  1. ファイルを探す.tex
  2. 指定されたファイルフィルタリング(egrep)
  3. テキスト検索はパターンを指定します\RequireLuaTeX(検索時に「\\」には\が含まれます)。
  4. 空の変数をチェックして空filenameの場合は、次の変数に移動します(grepが一致するものが見つからない場合に発生します)。
  5. 与えられたコマンドで完了

rmFinalとcommandなしでスクリプトをテストし、latex「エコー」して出力を確認することをお勧めします"$base"。 (すべての解決策について)ファイル名の空白の問題を想像できます。

...
  if [[ "$base" == "" ]];then continue; fi
  echo $base
done

必要に応じて、すべての検索パターンを抽出して、より良い調整と簡単な処理のために変数に入れることができます。

関連情報