
以前は、ディレクトリ内のすべての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
。(部分的にソースはマーティン)