というシェルスクリプトを作成する必要がありますchExt.sh
。ファイル拡張子を受け入れてから、複数のファイルを受け入れます。次に、ファイル拡張子を変更するか、ファイルが存在しないと宣言する必要があります。
./chExt.sh txt ocelot.cpp ../otherFolder/file.H cat.dog.TXT king cobra.dat
自動テスターテストの一般的なアイデアです。問題は、名前にスペースが含まれているファイルを処理する方法がわからないことです。
私のコードは次のとおりです
newExt="$1"
shift
for x in $*
do
fileName="$x"
if test -f "$fileName";
then
name=$(echo "$fileName" | rev | cut -f 2- -d '.' | rev)
newName="$name.$newExt"
if test "$newName" != "$fileName";
then
mv "$x" "$newName"
fi
else
echo "$fileName: No such file"
fi
done
ベストアンサー1
ファイル名を引用しないと、シェルはこれが2つの引数(および)foo bar.txt
ではなく1つの引数であることを知りません。したがって、次のようにスクリプトを呼び出す必要があります。foo
bar.txt
./chExt.sh txt ocelot.cpp ../otherFolder/file.H cat.dog.TXT "king cobra.dat"
次の問題は、変数が展開されると結果の値が空のスペースで分割(または$IFS
変数に設定された値)。したがってfor i in $*
、を書くと$*
スペースが拡張され分割されます。だからそれは一度の繰り返しと次の繰り返しになります$i
。回避策は、拡張したい変数が分割されないように引用することです。king
cobra.txt
これは次の質問につながります。$*
間の違い$@
。使用すると、"$*"
引数はすべて1つの長い文字列として扱われます。
$ cat foo.sh
#!/bin/sh
for i in "$*"; do
echo "$i"
done
$ foo.sh foo "bar baz"
foo bar baz
上記を以下と比較してみてください。
#!/bin/sh
for i in "$@"; do
echo "$i"
done
$ foo.sh foo "bar baz"
foo
bar baz
ご覧のとおり、使用すると"$@"
予想される効果があり、スペースを含む引数を含む各入力引数は個別に処理されます。
最後に、スクリプトは-
オプションに対応する文字と次に始まるファイル名もブロックします(たとえば、名前付きecho
ファイルを試してみてください)。-new
拡張を削除するより良い方法は、シェルのデフォルトの拡張を使用することです。文字列操作関数。変数の末尾から、${var%.*}
aとゼロ以上の文字に一致する最も短い文字列を削除します。.
つまり、拡張です。次に、次から始まるファイル名も処理できるように、オプションの終わりと引数の始まりを示すためにto--
を追加する必要があります(ガイド10を参照)。mv
-
ここ)。
したがって、改善され動作するスクリプトのバージョンは次のとおりです。
#!/bin/sh
newExt="$1"
shift
for fileName in "$@"
do
if test -f "$fileName";
then
# name=$(echo "$fileName" | rev | cut -f 2- -d '.' | rev)
name=${fileName%.*}
newName="$name.$newExt"
if test "$newName" != "$fileName";
then
mv -- "$fileName" "$newName"
fi
else
printf '%s: No such file\n' " $fileName"
fi
done
追加資料: