Это потому, что оператор `` `не для сложных сценариев. Это полезно для запуска single команды (и чтения ее вывода). За ней нет оболочки для хранения изменений среды между его вызовами и после вашего сценария Ruby прекращается.
В системах Linux каждый процесс имеет свой собственный путь "текущего каталога" (его можно найти в / proc / ‹pid› / cwd). Изменение каталога в процессе не влияет на родительские процессы (оболочка, из которой вы запускаете программу). Если cd
встроенный двоичный файл, он может изменить только свой текущий каталог, а не родительский процесс (поэтому команда cd
может быть только встроенной).
Примечание
Если Ruby-скрипт должен выполняться из оболочки и должен влиять на текущий путь к каталогу оболочки, можно сделать "хитрость". Вместо того, чтобы запускать команды из самого Ruby, выведите эти команды в stdout, а затем source
в оболочку, из которой вы запускали скрипт Ruby. Команды не будут выполняться отдельным процессом оболочки, поэтому все cd
s будут вступать в силу в текущем экземпляре оболочки.
Итак, вместо
ruby run_commands.rb
напишите в вашем shell-скрипте что-то вроде этого:
source <(ruby prepare_and_print_commands.rb)
Shell
класс
Но в Ruby есть удобный инструмент для сценариев командной строки - Shell
класс! Он имеет предопределенные сокращения для часто используемых команд (таких как cd
, pwd
, cat
, echo
и т. Д.) И позволяет определять свои собственные (он поддерживает команды и псевдонимы )! Также он прозрачно поддерживает перенаправление ввода / вывода с использованием операторов |
, >
, <
, >>
, <<
Ruby.
Работа с Shell
не требует пояснений в большинстве случаев. Взгляните на несколько простых примеров.
Создание объекта оболочки и изменение каталога
sh = Shell.new
sh.cd '~/tmp'
# or
sh = Shell.cd('~/tmp')
Работа в текущем каталоге
puts "Working directory: #{sh.pwd}"
(sh.echo 'test') | (sh.tee 'test') > STDOUT
# Redirecting possible to "left" as well as to "right".
(sh.cat < 'test') > 'triple_test'
# '>>' and '<<' are also supported.
sh.cat('test', 'test') >> 'triple_test'
(Обратите внимание, что скобки необходимы иногда из-за приоритета «перенаправления» операторов. Кроме того, вывод команды не будет выводиться на стандартный вывод по умолчанию, поэтому необходимо указать, что используется > STDOUT
или > STDERR
, если необходимо. )
Проверка свойств файла
puts sh.test('e', 'test')
# or
puts sh[:e, 'test']
puts sh[:exists?, 'test']
puts sh[:exists?, 'nonexistent']
(Работает аналогично функции test
в обычной оболочке.)
Определение пользовательских команд и псевдонимов
# name command line to execute
Shell.def_system_command 'list', 'ls -1'
# name cmd command's arguments
Shell.alias_command "lsC", "ls", "-CBF"
Shell.alias_command("lsC", "ls") { |*opts| ["-CBF", *opts] }
Имя определенной команды позже можно использовать для запуска ее точно так же, как она работает для предопределенных echo
или cat
, например.
Использование стека каталогов
sh.pushd '/tmp'
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT
sh.popd
sh.list > STDOUT
(sh.echo sh.pwd) > STDOUT
(Здесь используется пользовательская list
команда, определенная выше.)
Кстати, есть полезная команда chdir
для запуска нескольких команд в каталоге и после этого возврата в предыдущий рабочий каталог.
puts sh.pwd
sh.chdir('/tmp') do
puts sh.pwd
end
puts sh.pwd
Пропустить объект оболочки для группы команд
# Code above, rewritten to drop out 'sh.' in front of each command.
sh.transact do
pushd '/tmp'
list > STDOUT
(echo pwd) > STDOUT
popd
list > STDOUT
(echo pwd) > STDOUT
end
Дополнительные функции
Дополнительно Shell
имеет:
foreach
метод для перебора строк в файле или списка файлов в каталоге (в зависимости от того, указывает ли данный путь на файл или каталог),
jobs
и kill
команды для управления процессами,
- набор команд для работы с файлами (например,
basename
, chmod
, chown
, delete
, dirname
, rename
, stat
, symlink
),
- список
File
синонимов методов (directory?
, executable?
, exists?
, readable?
и т. Д.),
- эквивалентно
FileTest
методам класса '(syscopy
, copy
, move
, compare
, safe_unlink
, makedirs
, install
).