Запуск нескольких команд в одной строке в оболочке - PullRequest
318 голосов
/ 27 февраля 2011

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

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

Итак, /templates/apple будет скопирован в /templates/used И /templates/inuse а затем я хочу удалить оригинал.

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

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

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

Это правильный синтаксис?

Ответы [ 6 ]

647 голосов
/ 27 февраля 2011

Вы используете | (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 при ошибке.
69 голосов
/ 27 февраля 2011

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

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

cp file1 file2 ; cp file1 file3 ; rm file1

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

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

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

8 голосов
/ 27 февраля 2011

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

6 голосов
/ 02 октября 2017

Другим вариантом является ввод 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

2 голосов
/ 27 февраля 2011

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

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

1 голос
/ 27 февраля 2011

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...