Выполнение управляет содержащий пространство в ударе

У меня есть файл, названный cmd, который содержит список команд Unix следующим образом:

hostname
pwd
ls  /tmp
cat /etc/hostname
ls -la
ps -ef | grep java
cat cmd

У меня есть другой сценарий, который выполняет команды в cmd как:

IFS=$'\n'
clear
for cmds in `cat cmd`
do
        if [  $cmds ] ; then
        $cmds;
        echo "****************************";
        fi
done

Проблема состоит в том, что команды в cmd без пробелов хорошо работают, но те, которые имеют пробелы, правильно не интерпретируются сценарием. Следующее является выводом:

patrick-laptop
****************************
/home/patrick/bashFiles
****************************
./prog.sh: line 6: ls  /tmp: No such file or directory
****************************
./prog.sh: line 6: cat /etc/hostname: No such file or directory
****************************
./prog.sh: line 6: ls -la: command not found
****************************
./prog.sh: line 6: ps -ef | grep java: command not found
****************************
./prog.sh: line 6: cat cmd: command not found
****************************

Что я пропускаю здесь?

11
задан Peter Mortensen 18 November 2019 в 12:49
поделиться

5 ответов

Попробуйте изменить одну строку на eval $ cmds , а не просто на $ cmds

16
ответ дан 3 December 2019 в 05:14
поделиться

Вы можете заменить свой скрипт командой

sh cmd

. Работа оболочки заключается в том, чтобы читать команды и запускать их! Если вам нужны индикаторы вывода / прогресса, запустите оболочку в подробном режиме

sh -v cmd
3
ответ дан 3 December 2019 в 05:14
поделиться

Изменить: Оказывается, это не работает на каналах и перенаправлении. Спасибо, Андомар.

Вам нужно снова изменить IFS внутри цикла, чтобы bash знал, где разделить аргументы:

IFS=$'\n'
clear
for cmds in `cat cmd`
do
    if [ $cmds ] ; then
        IFS=$' \t\n' # the default
        $cmds;
        echo "****************************";
        IFS=$'\n'
    fi
done
1
ответ дан 3 December 2019 в 05:14
поделиться

РЕДАКТИРОВАТЬ: В комментарии Бена Бланка указано, что мой старый ответ был неправильным, спасибо.

Похоже, вы выполняете команды как одну строку, поэтому bash видит их как скрипт / имя исполняемого файла.

Один из способов избежать этого - вызвать команду bash. Изменение: с

    if [  $cmds ] ; then
    $cmds;
    echo "****************************";
    fi

на

    if [  $cmds ] ; then
    bash -c $cmds
    echo "****************************";
    fi
0
ответ дан 3 December 2019 в 05:14
поделиться

Мне лично этот подход больше нравится - я не хочу изменять IFS , если мне это не нужно. Вам действительно нужно использовать eval, если вы собираетесь использовать каналы в своих командах. Канал должен обрабатываться оболочкой, а не командой. Я считаю, что оболочка разбирает каналы до раскрывающихся строк.

Обратите внимание, что если ваш файл cmd содержит команды, которые принимают ввод, возникнет проблема. (Но вы всегда можете создать новый fd для команды чтения, из которой будет выполняться чтение.)

clear
while read cmds
do
        if [ -n "$cmds" ] ; then
        eval $cmds
        echo "****************************";
        fi
done < cmd
2
ответ дан 3 December 2019 в 05:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: