특정 파일 목록을 제외하고 파일 이름이 패턴과 일치하는 파일에 대해 명령을 실행합니다.

특정 파일 목록을 제외하고 파일 이름이 패턴과 일치하는 파일에 대해 명령을 실행합니다.

다음 스크립트는 .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

원하는 경우 모든 검색 패턴을 추출하여 더 나은 조정과 손쉬운 처리를 위해 변수에 넣을 수 있습니다.

관련 정보