bash / Makefileの引数としてSTDOUTを使用し、スペースを正しく処理します。

bash / Makefileの引数としてSTDOUTを使用し、スペースを正しく処理します。

これはbash構文の精神的な訓練に近いです。私たちが一緒に解決できるように、これをパズルだと思うように招待します。またはbashを理解するための挑戦として。

質問

たとえば、マイフォルダには3つのファイルがあります./etc

  • ./etc
    • foo.txt.example
    • bar.txt.example
    • hello world.txt.example (はい、このファイルにはスペースがあります)

上記のファイルに基づいてこれらのターゲットを実行するためのターゲットを構築しました。動作するタスクは次のとおりです。

make "etc/foo.txt"
make "etc/bar.txt"
make "etc/hello world.txt"

したがって、理論的には、すべてのターゲットを実行するために次のコマンドを作成できます。

make "etc/foo.txt" "etc/bar.txt" "etc/hello world.txt"

私の質問は次のとおりです。すべてを検索するbashスクリプトを書くことはできますか? ./etc/*.txt.example ファイル名と上記のコマンドを設定しますか?

必要

  1. 答えはbashコマンド形式またはMakefileターゲット定義形式でなければなりません。
  2. ほとんどのLinux環境では、デフォルトで実行する必要があります。一般的でないパッケージをインストールする必要はありません。

私が試したこと

Makefileで上記のすべてのファイル名を取得する方法を見つけました。

txt:
    for fn in "etc/*.txt.example"; do \
        echo "etc/$$(basename -s ".example" "$$fn")"; \
    done

これは基本的にbashで実行することを意味します。

for fn in "etc/*.txt.example"; do \
    echo "etc/$(basename -s ".example" "$fn")"; \
done

次の出力を提供します。

etc/foo.txt
etc/bar.txt
etc/hello world.txt

このループの出力を別のコマンドの入力として使用すると、そのコマンドはすべてのスペースを引数の区切り文字として扱うようです。だからこれ:

make $(for fn in "etc/*.txt.example"; do \
    echo "etc/$(basename -s ".example" "$fn")"; \
done)

実際には次のようになります。

make "etc/foo.txt" "etc/bar.txt" "etc/hello" "world.txt"

ループの出力を空白を正しく保持する引数に変換する方法はありますか?

ベストアンサー1

配列を使用できます。

# Get all example files in an array
examples=(etc/*.example)
# Strip the .example suffix from every element of the array
make "${examples[@]%.example}"

または、GNU find、sed、および xargs がある場合 (つまり、ヌル区切り文字をサポート):

find etc -iname '*.example' -print0 | sed -z 's/\.example$//' | xargs -0 make

おすすめ記事