LinuxForum.Fans
Тема

[Решено] shell - работа с файлами и командами

Автор: Jonikru 21 сообщений 6641 просмотров 🔒 закрыта
#39736

В общем проблема возникла в условии, вроде простое, но понять не могу. Может просто уже запарился.

Второе условие в if не верно, а именно в отрицании проблема, но как организовать нормально не могу понять. Поискал в инете, везде простые условия в "ифе", такого не встретил...

text

#!/bin/sh

if [ -z `$1` || ! -f `$2` ] #если строка 1 пуста или файла 2 не существует then echo "Неправильно заданы входные параметры" exit 1 fi

#39743

надо использовать ключик -o , а не ||
использование квадратных скобок, обозначает вызов команды test ( man test)
надо как то так:

text

if [ \( -z "$1" \) -o \! \( -f "$2" \) ]
then
  echo "Неправильно заданы входные параметры"
  exit 1
fi
#39745

Спасибо! Точно! Я просто с bash прогу перегоняю в sh, первый раз это делаю, поэтому трудновато пока.

#39845

Или так

text
#!/bin/sh

if [ -z "$1" ] || [ ! -f "$2" ] #если строка 1 пуста или файла 2 не существует then echo "Неправильно заданы входные параметры" exit 1 fi

Пётр.

#39892

Peter, Да, так будет покрасивее!:)

Я тут что мог по исправлял, но толку нет - не работает. В цикле for, из файла надо брать по строчке, а в строчке хранится имя файла к которому нужно применить атрибуты команды(саму команду мы раньше писали). Т.е. мы берём из файла(filelist.txt) имя файла(1.txt, 2.txt, 3.txt), к которому нам нужно применить вводимые атрибуты команды. Для каждого файла мы можем применять разные атрибуты одной и той же команды(команду мы можем задать только один раз вначале).

Цикл for:

text

for fname in `cat $2`
do
    echo "Для файла '$fname' [Для окончания ввода введите STOP]:"
    REPLY=""
    cmd=$1
    while [ true ] 
    do
        echo $cmd
        read -p ': ' REPLY
        
        if [ ! $REPLY = 'STOP' ]
            then cmd=$cmd" "$REPLY
            else break
        fi
    done
    cmd=$cmd" "$fname
    eval $cmd
done

filelist.txt:

text

1.txt
2.txt
3.txt
#39951

Вот ещё вариант на tcsh,

text

#!/bin/tcsh
# ./script_name < file_with_files_names
# the next string is in nn
while ( 1 )
set nn = "$<"
if ( $nn != "" ) then
echo "nn="$nn   #your command 
else break
endif
end

предположим, он называется file_read, а файл с именами файлов - filelst,
тогда его вызов

text
./read_file < filelst

но он не будет работать со старыми версиями tcsh, т.к. в них вместо
пустой строки будет возвращаться символ с кодом \0274.
У меня есть и такой вариант.

Пётр.

#40056
Jonikru написал:
Я тут что мог по исправлял, но толку нет - не работает.

Ты бы сразу писал бы: что именно не работает, какие конкретно ошибки возникают.
Так сработает?

text

for fname in `cat $2`
do
echo "Для файла '$fname' [Для окончания ввода введите STOP]:"
REPLY=""
cmd=$1
while  true
 do
  echo $cmd
  read -p ': ' REPLY
  if [ ! "$REPLY" = 'STOP' ]
   then cmd="$cmd $REPLY"
   else break
  fi
 done
cmd="$cmd $fname"
eval $cmd
done
#40060

Peter

text

./file_read < filelst
bash: ./file_read: /bin/tcsh: плохой интерпретатор: No such file or directory

Естественно такой файл существует и всё норм.
Такие ситуации иногда возникают если между первой строкой "#!/bin/tcsh" и кодом не пропущена строка, но я всё это сделал. Ещё могла случится ошибка в том случае, если мы копируем код с 'MS Windows', т.к. в винде в конце строки остаются невидимые специальные символы окончания строки, но я всё почистил. Не понятно в чём проблема!

inneska

Вот лог консоли, после ваших изменений:

text

~/Документы/Lab_2$ ./Lab_2 ls filelist.txt
Введите список аргументов для команды 'ls':
Для файла '1.txt
2.txt
3.txt' [Для окончания ввода введите STOP]:
ls
: -l
 -l
: STOP
: not found
: not foundtxt
eval: 3: 3.txt: not found

Вот полный текст программы!

text

#!/bin/sh

if [ -z "$1" ] || [ ! -f "$2" ] #если строка 1 пуста или файла 2 не существует then echo "Неправильно заданы входные параметры" exit 1 fi

IFS=$'\n' echo "Введите список аргументов для команды '$1':"

for fname in `cat $2` do echo "Для файла '$fname' [Для окончания ввода введите STOP]:"

REPLY=""

cmd=$1

while true do echo $cmd read -p ': ' REPLY if [ ! "$REPLY" = 'STOP' ] then cmd="$cmd $REPLY" else break fi done cmd="$cmd $fname" eval $cmd done

#40064

Вот это зачем?

Jonikru написал:
IFS=$'\n'

Попробуй убрать.
И вот это

Jonikru написал:
cmd=$1
, я бы заковычела
text

cmd="$1"
#40585

И так, программа работает, но остались непонятные вещи. Для работоспособности программы в файле filelist.txt имена фалов нужно располагать в строчку а не в столбик, иначе получается белиберда!

Перед командой eval "$cmd", я написал echo $cmd дабы наглядно наблюдать что же это у нас там получается. А получается странное. Если мы команде не передаём никаких параметров, то в конце имени файла появляется откуда-то буква t, откуда она я понять не могу. Если ввести параметры, то буквы t нет.

Самое главное! Проблема с eval! Она всё делает, но почему-то появляется сообщение ": No such file or directory". Нормальных манов по eval я не нашёл, так что толком не понял как она работает, если не трудно объясните или поделитесь ссылкой!

Терминал:

text

myubuntu:~/Документы/Lab_2$ ./Lab_2 cat filelist.txt
Введите список аргументов для команды 'cat':
Для файла '1.txt' [Для окончания ввода введите STOP]:
cat
: STOP
 1.txtt
: No such file or directory
Это первый файл!
Для файла '2.txt' [Для окончания ввода введите STOP]:
cat
: -u
 -u
: STOP
 -u 2.txt
: No such file or directory
Это второй файл!
Для файла '3.txt' [Для окончания ввода введите STOP]:
cat
: STOP
 3.txtt
: No such file or directory
Это третий файл!

Текст программы:

text

#!/bin/sh

if [ -z "$1" ] || [ ! -f "$2" ] #если строка 1 пуста или файла 2 не существует then echo "Неправильно заданы входные параметры" exit 1 fi

echo "Введите список аргументов для команды '$1':"

for fname in `cat $2` do echo "Для файла '$fname' [Для окончания ввода введите STOP]:" REPLY="" cmd="$1" while true do echo "$cmd" read -p ': ' REPLY if [ ! "$REPLY" = 'STOP' ] then cmd="$cmd $REPLY" else break fi done cmd="$1 $cmd $fname" echo $cmd eval "$cmd" done

#40590
Jonikru написал:
cmd="$1"
Jonikru написал:
cmd="$1 $cmd $fname"

У тебя получается что-то типа
cat cat 1.txt
Он и ругается, что файла с именем cat нет

#40593

Проверял тогда получается так:

text

myubuntu:~/Документы/Lab_2$ ./Lab_2 cat filelist.txt
Введите список аргументов для команды 'cat':
Для файла '1.txt' [Для окончания ввода введите STOP]:
cat
: STOP
 1.txt
: not foundt
Для файла '2.txt' [Для окончания ввода введите STOP]:
cat
: -u
 -u
: STOP
 -u 2.txt
: not foundt
Для файла '3.txt' [Для окончания ввода введите STOP]:
cat
: STOP
 3.txt
: not foundt
#40596

наверно дело в области видимости переменных.....
какой у тебя shell ?
sh --version

#40601

Ты будешь смеяться, но не получается посмотреть версию oO

Всё сделал, заработало!
inneska, спасибо тебе большое за помощь!

Для будущего поколения выкладываю.

Задание:
Написать командный файл, обеспечивающий применение команды, указанной в качестве первого аргумента к файлам, список которых содержится в заданном вторым аргументом файле. Для каждого из этих файлов необходимо запрашивать у пользователя ввода дополнительных (второго и последующих) параметров, которые надо передать команде.

Код программы:

text

#!/bin/sh

if [ -z "$1" ] || [ ! -f "$2" ] #если строка 1 пуста или файла 2 не существует then echo "Неправильно заданы входные параметры" exit 1 fi

echo "Введите список аргументов для команды '$1':"

for fname in `cat $2` do echo "Для файла '$fname' [Для окончания ввода введите STOP]:" REPLY="" cmd="" echo "$1" while true do read -p ': ' REPLY if [ ! "$REPLY" = 'STOP' ] then cmd="$cmd $REPLY" else break fi done cmd="$1 $cmd $fname" eval $cmd done

#40606

Поколение пусть само старается.
А версия - "bash -version", причём это в "man bash" в самом начале.

Пётр.

#40624
Peter написал:
А версия - "bash -version", причём это в "man bash" в самом начале.

Петр, а у него не bash, у него какой то непонятный sh

Jonikru написал:
#!/bin/sh
Jonikru написал:
Я просто с bash прогу перегоняю в sh

oO

#40632

Ссылка


Командный язык shell (в переводе - раковина, скорлупа)
фактически есть язык программирования очень высокого уровня. На
этом языке пользователь осуществляет управление компьютером.
Обычно, после входа в систему вы начинаете взаимодействовать с
командной оболочкой (если угодно - она начинает взаимодействовать
с вами). Признаком того, что оболочка (shell) готова к приему
команд служит выдаваемый ею на экран промптер. В простейшем
случае это один доллар ("$").
Shell не является необходимым и единственным командным
языком (хотя именно он стандартизован в рамках POSIX [POSIX
1003.2] - стандарта мобильных систем). Например, немалой
популярностью пользуется язык cshell, есть также kshell, bashell
(из наиболее популярных в последнее время) и другие. Более того,
каждый пользователь может создать свой командный язык. Может
одновременно на одном экземпляре операционной системы работать с
разными командными языками.
ОБРАТИТЕ ВНИМАНИЕ. shell - это одна из многих команд UNIX.
То есть в набор команд оболочки (интерпретатора) "shell" входит
команда "sh" - вызов интерпретатора "shell". Первый "shell"
вызывается автоматически при вашем входе в систему и выдает на
экран промтер. После этого вы можете вызывать на выполнение любые
команды, в том числе и снова сам "shell", который вам создаст
новую оболочку внутри прежней.
#40641

Jonikru, я думаю, что тут все знают что такое shell, и что bash это одна из его разновидностей.
Остается только загадкой какая конкретно у тебя версия sh :P
Во многих современных линуксах /bin/sh - это символьная ссылка на /bin/bash
В некоторых линуксах /bin/sh - это ссылка на /bin/dash

#40646

Я без понятия, я себе Ubuntu 9.10 поставил на VirtualBox.

Кстати этот фактор пугает, ведь в универе точно нет символьных ссылок!:) Так что ещё не понятно что я тут дома натворил.

#40651

в убунте /bin/sh -> /bin/dash
Можно проверить
ls -l /bin/sh
А в институте какой линукс?
Вообще не переживай, должно сработать и в институте, даже если там что-то другое

Войдите или зарегистрируйтесь, чтобы ответить.