Run a command on files with filenames matching a pattern, excluding a particular list of files
-L
flag to Grep list files not matching a pattern. You want -l
instead. Also, Grep needs to see double-backslash to match a single backslash.
Since you are in Bash, let us get hold of some useful constructs.
#!/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
expands to all files in the current directory tree that end in.tex
but whose basename is notfoo.tex
,bar.tex
norbaz.tex
. Bothglobstar
andextglob
are required for this operation."${filenames[@]/%.tex/.pdf}"
expands to all elements of the array, substituting each trailing.tex
by.pdf
.
Since Latexmk can be given multiple files as arguments, we could skip for-loops.
With zsh
, you can turn an array into a pattern that matches any of its elements by joining with |
with the j[|]
parameter expansion flag the elements inside which the glob characters have been escaped with the b
parameter expansion flag:
#! /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
Or you could use the e
glob qualifier to check if the t
ail of the file path is in the array:
#! /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
The way I approach this kind of problem is to turn the list of file names/patterns into a hash that has instant lookup with no searching required. (Note that the excludedFiles
patterns such as z*.tex
are expanded as part of the assignment, not as part of the hashing loop. For example, if there are three files matching the z*.tex
glob, then excludedFiles
will contain three entries rather than the one pattern, and the hashing loop will iterate three times.)
# 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