Короткий ответ
Чтобы скопировать myfile.txt
в /foo/bar/myfile.txt
, используйте:
mkdir -p /foo/bar && cp myfile.txt $_
Как это работает?
В этом есть несколько компонентов, поэтому я расскажу о синтаксисе шаг за шагом.
Утилита mkdir , , как указано в стандарте POSIX , создает каталоги. Аргумент -p
, согласно документам, приведет к mkdir до
Создание любых отсутствующих компонентов промежуточного пути
означает, что при вызове mkdir -p /foo/bar
, mkdir создаст /foo
и /foo/bar
, если /foo
еще не существует. (Без -p
он выдаст ошибку.
Оператор списка &&
, как описано в стандарте POSIX (или, если хотите, Руководство по Bash ), приводит к тому, что cp myfile.txt $_
выполняется только если mkdir -p /foo/bar
успешно выполняется. Это означает, что команда cp
не будет пытаться выполнить, если mkdir
завершится неудачно для , это одна из многих причин, по которой она может завершиться неудачей .
Наконец, $_
, который мы передаем в качестве второго аргумента cp
, является «специальным параметром», который может быть полезен для избежания повторения длинных аргументов (например, путей к файлам) без необходимости сохранять их в переменной. В Баш ручной , это:
расширяется до последнего аргумента предыдущей команды
В данном случае это /foo/bar
, которое мы передали mkdir
. Таким образом, команда cp
расширяется до cp myfile.txt /foo/bar
, что копирует myfile.txt
во вновь созданный каталог /foo/bar
.
Обратите внимание, что $_
является , а не частью стандарта POSIX , поэтому теоретически вариант Unix может иметь оболочку, которая не поддерживает эту конструкцию. Тем не менее, я не знаю никаких современных оболочек, которые не поддерживают $_
; конечно, Bash, Dash и Zsh все делают.
Последнее замечание: команда, которую я дал в начале этого ответа, предполагает, что в именах ваших каталогов нет пробелов. Если вы имеете дело с именами с пробелами, вам нужно заключить их в кавычки так, чтобы разные слова не рассматриваются как разные аргументы mkdir
или cp
. Таким образом, ваша команда будет выглядеть так:
mkdir -p "/my directory/name with/spaces" && cp "my filename with spaces.txt" "$_"