Выполнение нескольких команд в одной строке в оболочке

Скажем, у меня есть файл /templates/apple, и я хочу

  • поставьте его в двух разных местах, а затем
  • удалите оригинал.

Итак, /templates/apple будет скопирован в /templates/used И /templates/inuse и после этого Id хотел бы удалить оригинал.

Является ли cp лучшим способом для этого, а затем rm? Или есть лучший способ?

Я хочу сделать все это в одной строке, поэтому я думаю, что это будет выглядеть примерно так:

cp /templates/apple /templates/used | cp /templates/apple /templates/inuse | rm /templates/apple

Является ли это правильным синтаксисом?

Ответ 1

Вы используете | (pipe), чтобы направить вывод команды в другую команду. То, что вы ищете, - это оператор && для выполнения следующей команды, только если предыдущий преуспел:

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

Или

cp /templates/apple /templates/used && mv /templates/apple /templates/inuse

Подводя итог (не исчерпывающе) bash командных операторов/разделителей:

  • | трубы (конвейеры) стандартного вывода (stdout) одной команды в стандартный ввод другого. Обратите внимание, что stderr по-прежнему входит в пункт назначения по умолчанию, независимо от того, что произойдет.
  • |& пропускает как stdout, так и stderr одной команды в стандартный ввод другого. Очень полезно, доступно в bash версии 4 и выше.
  • && выполняет правую команду && только в том случае, если предыдущий преуспел.
  • || выполняет правую команду || только с предыдущей неудачей.
  • ; выполняет правую команду ; всегда независимо от того, была ли предыдущая команда успешной или неудачной. Если ранее не был вызван set -e, что приводит к ошибке bash при ошибке.

Ответ 2

Почему бы не cp перейти в местоположение 1, а затем mv в местоположение 2. Это позаботится об "удалении" оригинала.

И нет, это не правильный синтаксис. | используется для вывода "трубы" из одной программы и превращения ее в ввод для следующей программы. Вы хотите ;, который разделяет несколько команд.

cp file1 file2 ; cp file1 file3 ; rm file1

Если вам требуется, чтобы отдельные команды ДОЛЖНЫ преуспеть до того, как можно будет запустить следующий, то вместо этого вы должны использовать &&:

cp file1 file2 && cp file1 file3 && rm file1

Таким образом, если какая-либо из команд cp не работает, rm не будет выполняться.

Ответ 3

Обратите внимание, что cp A B; rm A точно mv A B. Это будет быстрее, так как вам не нужно фактически копировать байты (при условии, что пункт назначения находится в одной и той же файловой системе), просто переименуйте файл. Итак, вы хотите cp A B; mv A C

Ответ 4

Попробуйте это.

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

Ответ 5

Другой вариант - набрать Ctrl+V Ctrl+J в конце каждой команды.

Пример (замените # на Ctrl+V Ctrl+J):

$ echo 1#
echo 2#
echo 3

Выход:

1
2
3

Это приведет к выполнению команд независимо от того, были ли предыдущие неудачны.

То же, что: echo 1; echo 2; echo 3

Если вы хотите остановить выполнение неудачных команд, добавьте && в конце каждой строки, кроме последней.

Пример (замените # на Ctrl+V Ctrl+J):

$ echo 1 &&#
failed-command &&#
echo 2

Вывод:

1
failed-command: command not found

В zsh вы также можете использовать Alt+Enter или Esc+Enter вместо Ctrl+V Ctrl+J

Ответ 6

Использование труб кажется мне странным. В любом случае вы должны использовать логический оператор and Bash:

$ cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apples

Если команды cp выходят из строя, rm не будет выполняться.

Или вы можете сделать более сложную командную строку, используя цикл for и cmp.

Ответ 7

Очень просто: Просто используйте && между каждой командой

Логика cp file1 file2 && cp file1 file3 && rm file1

EG 1:

cp /templates/apple /templates/used && mv /templates/apple /templates/inuse

EG 2:

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

EDIT: Он работает для меня.