「ファイルが見つかりません」プレーンテキストの代わりにコマンドを使用すると

「ファイルが見つかりません」プレーンテキストの代わりにコマンドを使用すると

良い一日、

リモート フォルダー内のファイルに効率的にアクセスする方法を探しています。パスに対していくつかのコマンドを定義しました。

以下のコードの 6 行目は機能し、正しいファイルが含まれていますが、8 行目では「ファイルが見つかりません」と表示されます。しかし、これら 2 つのパスはまったく同じであるべきではないでしょうか。このようにコマンドを連結することはできないのでしょうか。

1 \newcommand{\results}{../../code/data/results/}
2 \newcommand{\synthetic}{\results synthetic/}
3 \newcommand{\sine}[1]{sine_#1hz.pdf}
4
5
6 \includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}
7
8 \includegraphics[width=.3\linewidth]{\synthetic \sine{100}}

おそらく、私が何か明らかなことを見逃しているのでしょう。コマンドでパス名を扱うのは今回が初めてです。私が見逃しているものを誰か知っていますか?

乾杯

編集: これは完全なコード例です:

\documentclass[]{article}
\usepackage{graphicx}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic \sine{100}}

\end{document}

このコードは、必要なファイルを示しています。最後から 2 番目の行でコメントバックすると、次のエラーが発生します。

File `../../code/waveletTest/data/results/synthetic/sine_100hz.pdf' not found. ...width=.3\linewidth]{\synthetic \sine{100}}

答え1

私のシステムでは、-command の処理の途中で\includegraphics次のシーケンスが返されます。
\filename@parse{\synthetic\sine{100}}

\filename@parseはLaTeX 2εカーネルのルーチンであり、引数を次のように分割する。

  1. ファイルへのパス。ファイルへのパスはマクロに保存されます\filename@area
  2. ファイル名(拡張子なし)。ファイル名(拡張子なし)は に保存されます\filename@base
  3. ファイル名の拡張子。ファイル名の拡張子は に格納されます\filename@ext。拡張子がない場合は は\filename@extと等しくなります\relax

何が起こるか:

私のシステムでは\filename@parse、構文: は次のように定義されます。
\filename@parse{⟨file-path/filename-specification⟩}

> \filename@parse=macro:
#1->\let \filename@area \@empty \expandafter \filename@path #1/\\

したがって、マクロと等しくなるように\filename@parse初期化します。マクロは、トップレベル展開中にトークンストリームから消え、引数を処理せず、空の/トークンをまったく含まない置換テキストを配信します。そして、引数の最初のトークンに「ヒット」した後、ルーチンを呼び出します。\filename@area\empty\empty\filename@path\expandafter 一度/\\結果に追加します。(引数#1が空の場合、追加されたスラッシュは/にヒットしますが\expandafter、明示的なスラッシュ文字トークン (catcode 12(other)) は拡張可能ではないため、害はありません。)

手順については\filename@path後ほど説明します。現時点ではこれだけです。\filename@path拡張不可能な明示的な文字トークンのシーケンスを処理するためにインデントされているこれは、ファイル パス/ファイル名指定 ( #1) を形成し、その後に、カテゴリ コード 12 (その他) の明示的なスラッシュ文字トークン/と、ファイル パス/ファイル名指定の終了の区切り文字/マーカーとして制御記号トークンが続きます\\

\expandafterしたがって、「一度ヒットする」\filename@parseことは、ファイル パス/ファイル名仕様を提供するための引数が、拡張不可能な明示的な文字トークンのシーケンスで構成されておらず、最上位レベルの拡張によって拡張不可能な明示的な文字トークンのシーケンスが生成されるマクロ トークンによって形成されている場合に行われます。
この「1 回のヒット」は、内部的に を使用する\expandafterなどのものでは、ファイル パス/ファイル名仕様をトークン シーケンスの観点からのみ提供できることを意味し、シーケンスの最初のトークンを1 回ヒットするだけで、ファイル パス/ファイル名仕様を形成する拡張不可能な明示的な文字トークンのシーケンス全体を取得するのに十分です。\includegraphics\filename@parse\expandafter

\expandafterシナリオでは、シーケンスの最初のトークンを1 回「ヒット」しても、拡張不可能な明示的な文字トークンのシーケンスの観点から、ファイル パス/ファイル名仕様全体 (完全に拡張) が生成されるわけではなく、さらに拡張作業を行う必要がある\synthetic \sine{100}シーケンスが生成されることに注意してください。\results synthetic/\sine{100}

したがって、コンポーネント (ファイルへのパス、拡張子なしのファイル名、ファイル名拡張子) の分割/結合は、\filename@pathおよびその基礎となるルーチンによって正しく実行されません。

次に、ファイル パス/ファイル名の指定が、拡張不可能な明示的な文字トークンのシーケンス (構文: ;はフォルダー/ディレクトリ区切り文字\filename@path) で提供されることを「想定」するルーチン は、次のように定義されます。
\filename@path ⟨file-path/filename-specification in terms of a sequence of non-expandable explicit character-tokens⟩/\\
/

> \filename@path=macro:
#1/#2\\->\ifx \\#2\\\def \reserved@a {\filename@simple #1.\\}\else \edef \filen
ame@area {\filename@area #1/}\def \reserved@a {\filename@path #2\\}\fi \reserve
d@a 

\filename@pathは再帰ループで、各反復で、ファイル名を示す最後のセグメントに達するまで、/ファイルパス/ファイル名指定の - で区切られた次のセグメントをマクロに追加します。次の (おそらく最後の) セグメントは にあります。その次のセグメントに続くセグメントは にあります。したがって、最後のセグメントの指標は が空であることです。が空であるかどうか のテストは次のとおりです。 ファイル名を示す最後のセグメントに達すると、マクロが呼び出され、最後のセグメント/ファイル名にドット ( ) が含まれているかどうか、したがってファイル名からファイル名拡張子を切り離す必要があるかどうかが確認されます。ファイル名拡張子を切り離す必要がある場合は、マクロ によって行われます。 \filename@area#1#2#2
#2
\ifx\\#2\\⟨tokens in case #2 is empty⟩\else⟨tokens in case #2 is not empty⟩\fi
\filename@simple.\filename@dot

\filename@simple構文: を、ファイル名を表す 最後の - 区切りセグメントで呼び出すと、シーケンスが最後のセグメントに追加されます。 したがって、ドットで区切られた引数と- 区切りの引数を収集し、 の空かどうかに応じて、セグメント内に存在するドットがドットで区切られた引数の区切り文字として使用されたのか、追加されたドットが使用されたのかを検出できます。
\filename@simple ⟨filename-specification in terms of a sequence of non-expandable explicit character-tokens⟩.\\
/.\\
\filename@simple#1\\#2#2

\filename@simpleは次のように定義されます。

> \filename@simple=macro:
#1.#2\\->\ifx \\#2\\\let \filename@ext \relax \else \edef \filename@ext {\filen
ame@dot #2\\}\fi \edef \filename@base {#1}

最後のセグメント/ファイル名にドットが含まれていない場合、.追加されたシーケンスの が の.\\区切り文字として使用され#1、 -delimited\\#2空になります。それ以外の場合、最後のセグメントの最初のドットが の区切り文字として使用され、#1-delimited\\#2空になりません。したがって、#2( \ifx\\#2\\...) が空であることは、最後のセグメントが (ドットで区切られた) 拡張子のないファイル名を形成するか、ドットによってファイル拡張子から区切られたファイル名を形成するかを示すものとして使用されます。 が#2空の場合、 は\filename@ext" \let" と等しくなります\relax。それ以外の場合、 を\filename@ext介してを定義するときに\edef\filename@dotが最初のドットの後ろのものに適用され、追加されたシーケンス が削除されます.\\。いずれの場合も、\filename@baseは最初のドットの前にあるものに展開するように定義されます。

\filename@dotは次のように定義されます。

> \filename@dot=macro:
#1.\\->#1

この\filename@parseメカニズムは素晴らしいです。しかし、いくつか制限があります。

たとえば、ファイル名には最大 1 つのドットが含まれると想定されます。

たとえば、最大 1 つのドットを含むファイル名の場合、ドットはファイル名 (拡張子なし) とファイル名拡張子 (空ではない) を区切るものと想定されます。ドットで終わるファイル名 (一部のファイル システムでは完全に「合法」) は、問題を引き起こす可能性があります。

たとえば、特別なカテゴリ コードを持つ特殊文字は考慮されません。たとえば、中括弧を含むファイル パス/ファイル名仕様では、中括弧が不均衡であったり、削除されたり、ドットやスラッシュが区切られた引数の区切り文字として解釈されないように「マスク」されたりすることがあります。このようなことは問題を引き起こします。たとえば、ハッシュを含むファイル パス/ファイル名仕様は、 などの一時マクロ\reserved@aや、ファイル パス/ファイル名仕様を分割した結果を保持するマクロを定義するときに問題を引き起こす可能性があります。

たとえば、引数の最初のトークンに対する /that による単一の「ヒット」によって\expandafter単一の拡張ステップ (→「トップレベル拡張」という用語の意味) がトリガーされれば、\filename@parse拡張不可能な明示的な文字トークンのシーケンスとしてファイル パス/ファイル名仕様全体を取得するのに十分であると想定されます。シナリオではこれは当てはまらないため、 がまだ拡張されていない間に分割が試行され\sine、ファイル名 (拡張子なし) とファイル名拡張子を区切るドットがメカニズムによって\filename@simpleまだ「認識」されません。したがって、シナリオでは、graphicx パッケージはファイル名拡張子が指定されていないと誤って「想定」します。graphicx パッケージがファイル名拡張子が指定されていないと「想定」した場合 (想定が正しいか誤っているかは関係ありません)、いくつかのデフォルト拡張子で試行します。

例えば、 の代わりに、、 など../../code/waveletTest/data/results/synthetic/sine_100hz.pdfを試行します。
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf.pdf
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf.png
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf.jpg

そのため、「H⟨戻る⟩" コンソール/画面にエラー メッセージがポップアップ表示されたら、次のようになります。

I could not locate the file with any of these extensions:
.pdf,.png,.jpg,.mps,.jpeg,.jbig2,.jb2,.PDF,.PNG,.JPG,.JPEG,.JBIG2,.JB2,.eps
Try typing  <return>  to proceed.
If that doesn't work, type  X <return>  to quit.

David Carlisle (graphicx-package の作成者) によるファイル名拡張子を省略するという提案は.pdf、ファイル名拡張子の存在を確認する前に展開することは、純粋主義者の心を満足させる方法では行われないとしても、ファイル名拡張子が指定されていないという graphicx-package の想定は正しく、したがって graphicx-package は、機能する方法でデフォルトの拡張子を試行する (graphicx-package は、、、
../../code/waveletTest/data/results/synthetic/sine_100hz.pdfなど
../../code/waveletTest/data/results/synthetic/sine_100hz.pngで試行する
../../code/waveletTest/data/results/synthetic/sine_100hz.jpg)
という事実に基づいています
。最初のものはすでに機能しています。

これらすべてはパッケージをロードすることで解決できますgrfファイル:

\documentclass[]{article}
\usepackage{graphicx}
\usepackage{grffile}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

\includegraphics[width=.3\linewidth]{\synthetic\sine{100}}

\end{document}

ところで:

非常に特殊なケースでは、次\filename@parseを追加することで、メカニズムを騙してファイル名拡張子を正しく切り離すことができます\expandafter

\documentclass[]{article}
\usepackage{graphicx}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

\includegraphics[width=.3\linewidth]{\expandafter\synthetic\sine{100}}

\end{document}

少なくとも私のシステムではこれでうまくいきます。

これはファイル名拡張子を正しく切り離すことに注意してくださいしかし、これはファイルパスとファイル名を正しく分離しません.
ファイルパスは空とみなされます。ファイル名には
シーケンス\synthetic sine_100hzが使われます。
これは問題ではないようです。

しかし、これ\filename@parseは LaTeX 2ε カーネルのマクロです。また、最近 LaTeX 2ε カーネルには多くの変更と革新が加えられています。おそらく、\filename@parseあなたのシステムでは、私のシステムと同じようには動作しないでしょう。

\expandafterマクロの最上位展開から、展開不可能な明示的な文字トークンによるファイル パス/ファイル名仕様を取得するために、引数の最初のトークンを で 1 回ヒットする」という動作は から削除されないものと想定しています。したがって、ファイル パス/ファイル名仕様を取得するためにで 1 回ヒットする必要がある、いくつかの -expansion-tricks を適用できます\filename@parse
\romannumeral\expandafter

\documentclass[]{article}
\usepackage{graphicx}
\begin{document}

\newcommand{\results}{../../code/waveletTest/data/results/}
\newcommand{\synthetic}{\results synthetic/}
\newcommand{\sine}[1]{sine_#1hz.pdf}

%\includegraphics[width=.3\linewidth]{\synthetic sine_100hz.pdf}

\includegraphics[width=.3\linewidth]{\romannumeral0\expandafter\synthetic\sine{100}}

\end{document}

ここで何が起こりますか?

\filename@parse's は\expandafer「ヒット」します\romannumeral
その後、\romannumeralTeX の収集が開始されます。⟨番号⟩-数量は進行中です:

%\romannumeral-triggered gathering of a TeX-number-quantity is in progress:
0\expandafter\synthetic\sine{100}

LaTeXは数字を見つけて0それを破棄します。
次に、TeXを収集するプロセスです。⟨番号⟩-数量は、より多くの数字を集めるプロセス、またはTeXの収集を終了する何かに変換されます-⟨番号⟩-量:

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
\expandafter\synthetic\sine{100}

これで、LaTeX は を展開します\expandafter。展開の結果は\expandafterを展開します\sine

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
\synthetic sine_100hz.pdf

現在、LaTeX は拡張されています\synthetic

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
\results synthetic/sine_100hz.pdf

現在、LaTeX は拡張されています\results

%\romannumeral-triggered gathering of more digits is in progress; digit "0" found.
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf

ここで、LaTeX はドットを見つけます。そのドットは数字ではありません。スペース トークンとは異なり、ドットは破棄されません。スペース トークンと同様に、\romannumeralTeX (のコンポーネント) の収集をトリガーして終了します。⟨番号⟩-数量。したがって、LaTeX は 0 が正の数でない場合にのみ数字/数値を検出します0。正の数でない場合には\romannumeral、何もトークンを返しません。

%\romannumeral done.
../../code/waveletTest/data/results/synthetic/sine_100hz.pdf

関連情報