C ファイルをコンパイルするシェル スクリプト

C ファイルをコンパイルするシェル スクリプト

以前は、ディレクトリ内のすべてのFILE.cファイルをFILE.outにコンパイルするシェルスクリプトを使用していました。

私はそれを失くしてしまい、それを作り直そうとしています。次のようなものがあり、非常に似ていることは分かっていますが、どこが間違っているのかわかりません。

#!/usr/bin/env bash

for i in 'ls *.c'
do
    gcc -g3 -o3 $i -o {$i%.}.out
done

答え1

コマンドを実行する必要はありませんls *.c。Bash はワイルドカード パターンを自動的に展開します。そのため、どうしても Makefile を作成したくない場合は、次のようにします。

#!/usr/bin/env bash

for i in *.c
do
    echo "gcc -g3 -o3 $i -o ${i%.c}.out"
    # gcc -g3 -o3 "$i" -o "${i%.c}.out"
done

次のようなサンプルデータがあるとします。

$ ls -1
a.c
b.c
c.bash
c.c
d.c
e.c

スクリプトを実行中c.bash:

$ ./c.bash 
gcc -g3 -o3 a.c -o a.out
gcc -g3 -o3 b.c -o b.out
gcc -g3 -o3 c.c -o c.out
gcc -g3 -o3 d.c -o d.out
gcc -g3 -o3 e.c -o e.out

スクリプトを実行するには、上の行をコメントアウトしecho、そのgcc行のコメントを解除します。

答え2

あなたの質問を具体的に見ると、「どこで間違えたか」はパラメータの拡張にあるようです。ここで出力ファイルに名前を付けるときに i の値を変更しようとしていたと思います。

{$i%.} 

ドル記号の位置が間違っていると思います。おそらく次の意味だったのでしょう:

${i%.}

正直に言うと、元のファイル名から「.」が削除されるだけです。一方、「filename.c」は「filenamec.out」になります。おそらく、次のようになります。

${i%.*}

これにより、「filename.out」が生成されます。このパラメータ拡張構文は、「.」以降のすべてを非貪欲に削除することを意味します。貪欲に削除する場合、構文は次のようになります。

${i%%.*}

これがあなたのコードに関連する質問へのより良い答えになることを願っています。

答え3

forループは、意図した出力コマンドではなく、for i in 'ls *.c'リテラル文字列「 」をループしていますls *.c。これは、コマンド置換演算子(例for i in $(ls *.c); do...)を使用することで修正できますが、slmが指摘しているように彼の答えの中でforループでシェルのグロブ出力を使用できるため、コマンドはまったく必要ありません:)

この問題全体は、単純な makefile を使用するとより適切に解決できます。

CC = gcc
CFLAGS = -std=c99 -pedantic -D_XOPEN_SOURCE=600 -Wall -Werror -g
RM = rm -f
SRCS = $(wildcard *.c)
PROGS = $(patsubst %.c,%,$(SRCS))

.PHONY: all clean

all: $(PROGS)

%: %.c
    $(CC) $(CFLAGS) -g3 -o3 -o $@ $<

clean:
    $(RM) $(PROGS)

「Makefile」として保存し、 を実行しますmake。 を実行してコンパイルされたプログラムを削除します(クリーン)make clean。(部分的にソースはマーティン

関連情報