Почему кавычки необходимы для аргумента файлов при вызове этого скрипта Bash?

13

Я довольно новичок в скриптах Bash. У меня есть «тестовый скрипт», который я использовал в качестве основы для более продвинутого / полезного скрипта:

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

Когда я вызываю это без кавычек, он просто берет один файл в каталоге:

testscript *.txt

Но когда я вызываю его с кавычками, он работает правильно и выбирает все текстовые файлы:

testscript '*.txt'

Что здесь происходит?

gornvix
источник
Чтобы быть очень, очень ясным, правильный способ исправить это состоит в том, чтобы запустить 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, цитирование имеет решающее значение для предотвращения оболочки анализ, чтобы превратить его в два имени файла, одно имя myи одно имя file.txt. Всегда цитируйте пользовательский ввод и расширение глобуса, чтобы вы не были очень несчастны в один прекрасный день.
Сет Робертсон
2
И это не просто теоретический подход - Mac OS X когда-то поставлялся со скриптом обновления, который неправильно цитировал аргументы и в некоторых случаях приводил к удалению чужих жестких дисков.
пушистый
2
@fluffy, у тебя есть ссылка об этом?
Wildcard
@Wildcard К сожалению, я не могу найти какие-либо статьи об этом, но это было большой новостью в мире технологий, когда это произошло. Я хочу сказать, что это было в 2003/2004 или около того, когда Apple все еще понимала, что является дистрибьютором UNIX.
пушистый
1
@wildcard Ах, нашел это! xlr8yourmac.com/OSX/itunes2_erased_drives.html - на самом деле виновником был сценарий обновления iTunes.
пушистый
7

Без кавычек оболочка раскрывается *.txtперед вызовом скрипта, поэтому раскрывается $1только первый файл. На данный момент все txtфайлы являются аргументами вашего сценария (при условии, что их не слишком много).

С кавычками эта строка передается без расширения в сценарий, который затем позволяет forвыполнить расширение, как вы и надеялись.

Эрик Ренуф
источник