csh/sh для цикла - как?

я пытаюсь написать цикл for, который выполняет 2 скрипта на FreeBSD. Мне все равно, написано ли это на языке sh или csh. Я хочу что-то вроде:

for($i=11; $i<=24; $i++)
{
   exec(tar xzf 'myfile-1.0.' . $i);
   // detect an error was returned by the script
   if ('./patch.sh')
   {
      echo "Patching to $i failed\n";
   }
}

Кто-нибудь знает, как это сделать, пожалуйста?

Спасибо


person Paul J    schedule 13.05.2011    source источник
comment
Почему вы используете csh для сценариев - это НЕ то, для чего он был предназначен. Вместо этого используйте bash, ksh или даже sh.   -  person    schedule 13.05.2011
comment
нет выбора. это единственная оболочка на FreeBSD, которую я могу использовать. если я не могу использовать sh, и в этом случае я ищу решение sh.   -  person Paul J    schedule 13.05.2011
comment
@Нил - кто знает? Если да, то подойдет sh-скрипт.   -  person Paul J    schedule 13.05.2011


Ответы (5)


csh отлично выполняет циклы, проблема в том, что вы используете exec, который заменяет текущую программу (то есть оболочку) другой, в том же процессе. Так как другие предоставили версии sh, вот версия csh:

    #!/bin/csh
    set i = 11
    while ($i < 25)
        tar xzf "myfile-1.0.$i"

        # detect an error was returned by the script   
        if ({./patch.sh}) then     
            echo "Patching to $i failed"   
        endif
        @ i = $i + 1
    end

Не уверен насчет ./patch.sh, вы проверяете его существование или запускаете? Я запускаю его здесь и проверяю результат - true означает, что он вернул ноль. В качестве альтернативы:

        # detect an error was returned by the script   
        if (!{tar xzf "myfile-1.0.$i"}) then     
            echo "Patching to $i failed"   
        endif
person cdarke    schedule 13.05.2011
comment
Да, я согласен, но это не помогает ОП. - person cdarke; 22.05.2011
comment
Я предлагаю #!/bin/csh -f. -f указывает оболочке не использовать файлы запуска, .cshrc и .login, что ускоряет работу сценария и позволяет избежать зависимостей. (Это относится только к csh/tcsh; у sh и bash есть опция -f, но она совершенно другая.) - person Keith Thompson; 24.04.2013

Типичный способ сделать это в sh:

for i in $(seq 11 24); do 
   tar xzf "myfile-1.0$i" || exit 1
done

Обратите внимание, что seq не является стандартным. В зависимости от наличия инструментов вы можете попробовать:

jot 14 11 24

or

perl -E 'say for(11..24)'

or

yes '' | nl -ba | sed -n -e 11,24p -e 24q

Я сделал несколько изменений: я прерываю работу в случае сбоя tar и не выдаю сообщение об ошибке, так как tar должен выдавать сообщение об ошибке вместо сценария.

person William Pursell    schedule 13.05.2011
comment
FreeBSD включает в себя инструмент jot, похожий на seq. - person Allan Jude; 05.03.2013

Ух ты! Нет БАШ. И, вероятно, не Kornshell:

i=11
while [ $i -le 24 ]
do
    tar xzf myfile-1.0.$i
    i=`expr $i + 1`
    if ./patch.sh
    then
        echo "patching to $i failed"
    fi
done

Написано в чистой оболочке Борна, как и задумал Бог.

Обратите внимание, что вы должны использовать команду expr, чтобы добавить 1 к $i. Оболочка Bourne не занимается математикой. Обратные кавычки означают выполнение команды и помещение STDOUT из команды в $i.

Kornshell и BASH делают это намного проще, поскольку они могут выполнять математические операции и более сложные циклы for.

person David W.    schedule 13.05.2011

Я думаю, вы должны просто использовать bash. У меня его нет, поэтому я не могу его проверить, но что-то в этом роде должно работать:

for ((I=11; I<=24; I++)) ; do
   tar xzf myfile-1.0.$I || echo Patching to $I failed
done

РЕДАКТИРОВАТЬ: Просто прочитайте комментарии и узнайте, что в установке FreeBSD по умолчанию нет bash. Так что это может вообще не работать - я не уверен в различиях между (t) csh и bash.

person Axel    schedule 13.05.2011
comment
Я думаю, что никто не должен использовать башизмы, когда легко написать эквивалентное решение оболочки POSIX. All the world's a bash кажется мне версией 3-го тысячелетия All the world's a VAX. - person Jens; 26.08.2011

Что я только что сделал, так это следующее.

sh

Загрузите оболочку sh, а затем цикл for работает как в Linux.

for i in 1 2 3 4 5 6 7 8 9; do dd if=/dev/zero of=/tmp/yourfilename$i.test bs=52428800 count=15; done
person gnudna    schedule 21.06.2013