このBashスクリプトを呼び出すときに、ファイル引数に引用符が必要なのはなぜですか?


13

私は、Bashスクリプトを作成するのは初めてです。私は、より高度で便利なスクリプトの基礎として使用した「テストスクリプト」を持っています。

#!/bin/bash
files=$1
for a in $files
do
    echo "$a"
done

引用符なしでこれを呼び出すと、ディレクトリ内の1つのファイルが選択されます。

testscript *.txt

しかし、引用符で呼び出すと、正しく動作し、すべてのテキストファイルが選択されます。

testscript '*.txt'

ここで何が起こっていますか?


非常に明確にするために、これを修正する正しい方法は、スクリプトで実行for a in "$@"; do(またはfor a; do)することです。したがって、引用符を省略せずに、グロブを外部シェルに残します。
チャールズダフィー


これは一見の価値があります。 guide.bash.academy
vascowhite

回答:


29

プログラムを呼び出すとき

testscript *.txt

それからあなたの展開を行い、すべての値をうまくいきます。したがって、プログラムを次のように効果的に呼び出すことができます。

testscript file1.txt file2.txt file3.txt file4.txt

今、あなたのプログラムは $1いるだけなので、上でのみ動作しfile1.txtます。

コマンドラインで引用することにより、リテラル文字列を渡します *.txtをスクリプトに$1。それがに格納されます。あなたのforループは、それを展開します。

通常は使用します "$@"$1、このようなスクリプトではなくし。

これは、コマンドスクリプトシェルがグロビングを行わないCMDスクリプティングから来た人にとっては「落とし穴」です(既知のように)、常にリテラル文字列を渡します。


6
ちょうど使用して、(上記の回答の著者以外の人のために)明確にするために"$@"(とは対照的に、$@または$1 $2 $3)各ファイル名が引用されるようになります"file1.txt" "file2.txt"ためなどfile1.txt、これは無意味ですが、あなたが持っている場合my file.txt、引用はある重大なシェルを防ぐために解析して2つのファイル名に変換します。1つは名前付きmy、もう1つは名前付きfile.txtです。いつか非常に不幸にならないように、常にユーザー入力とグロブ拡張を引用してください。
セスロバートソン

2
これは単なる理論的なものではありません。MacOS Xには、引数を適切に引用せず、状況によっては人々のハードドライブを削除してしまうアップデートスクリプトが付属していたことがあります。
ふわふわ

2
@fluffy、それについてのリンクはありますか?
ワイルドカード

@Wildcard残念ながら、私はそれについての記事を見つけることができませんが、それが起こったとき、それは技術の世界で大きなニュースでした。AppleがUNIXディストリビューターであることのコツをつかんでいた頃の2003/2004年頃だったと言いたい。
ふわふわ

1
@wildcardああ、見つけた!xlr8yourmac.com/OSX/itunes2_erased_drives.html-犯人は実際にはiTunesアップグレードスクリプトでした。
ふわふわ

7

引用符がないと、シェル*.txtはスクリプトを呼び出す前に展開するため$1、最初に展開されるファイルのみが展開されます。すべてのtxtファイルは、その時点でのスクリプトへの引数です(多すぎないと仮定して)。

引用符を使用すると、その文字列はスクリプトに展開されることなく渡され、for希望どおりに展開が行われます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.