Простой скрипт bash не работает

Простой скрипт bash не работает

Этот скрипт должен копировать все файлы, имена которых указаны в качестве аргументов в командной строке, в домашний каталог пользователя. Если файлы не указаны, скрипт должен использовать read для запроса имен файлов и копировать все имена файлов, указанные в ответе, в домашний каталог пользователя.

if [ -z $1 ]
then
    echo provide filenames
    read $FILENAMES
else
    FILENAMES="$@"
fi

echo the following filenames have been provided: $FILENAMES
for i in $FILENAMES
do
    cp $i $HOME
done

Если я передаю аргументы как строку - это работает. Но если я передаю как "read $FILENAMES" - это не работает.

Наставник показывает то же самое решение на своих уроках, но не показывает, как оно работает. введите описание изображения здесь

ОБНОВЛЕНИЕ После того, как я ввел имена файлов в качестве аргументов, он выдает пустые строки и не копирует файлы в папку $HOME

[dmytro@oc1726036122 ~]$ cd Desktop/
[dmytro@oc1726036122 Desktop]$ . totmp 
provide filenames
one two
the following filenames have been provided:
the following filenames have been provided:
[dmytro@oc1726036122 Desktop]$

решение1

Объявляет readпеременные, а не читает их. Проще говоря, удалите $from readи все готово.

if [ -z $1 ]
then
    echo provide filenames
    read FILENAMES
else
    FILENAMES="$@"
fi

echo the following filenames have been provided: $FILENAMES
for i in $FILENAMES
do
    cp $i $HOME
done

EDIT: Я вижу, что вы используете команду source( .) для запуска скрипта.

[dmytro@oc1726036122 Desktop]$ . totmp

Это может быть нормально для этого конкретного скрипта, но никогда не делайте этого для сложных скриптов. В противном случае вы перенесете любую переменную или функцию из этого скрипта в свою оболочку. Просто используйтеbash totmp

решение2

Проблема, которая, по-видимому, блокирует вас, заключается в том, что readкоманда неверна, переданный ей аргумент должен быть именем переменной, поэтому его следует передавать без $( $точка развернет содержимое переменной, которая на тот момент будет пустой, поэтому результатом будет тетка readбез переданных ей имен переменных).

read FILENAMES

Есть еще одна проблема с проверкой отсутствия первого аргумента командной строки. Если его нет, то он $1будет расширяться до нуля (не до пустой строки), что может вызвать проблемы с командой [, поскольку [ -z ]на самом деле не должен быть допустимым, [ -z "" ]это то, что вы ожидаете проверить в этом случае. Короче говоря, вам нужно заключить эту переменную в кавычки:

if [ -z "$1" ]

Поскольку вы используете bash, вы также можете использовать [[ ... ]], что, как правило, лучше, поскольку это внутренняя команда (в этом случае эта команда должна работать без кавычек, но сохранение кавычек не повредит и выглядит хорошо).

(P.S. В этом скрипте так много всего неправильного, он настолько далек от лучших практик, что я действительно в ужасе от того, что кто-то этому учит. К сожалению, похоже, что планка для обучения bash действительно низкая, а руководства по нему действительно сложны, пока вы действительно не поймете его как следует, так что я не знаю, какой лучший совет по его правильному изучению тоже есть.)☹️

решение3

Команда readпринимает переменную, но вы уже ссылаетесь на значения переменной:

 #correct syntax
 read variable
 #wrong syntax
 read $variable

$variable— это значение variable, а в начале скрипта оно не установлено/пустое.

Связанный контент