Linux: Копирование и создание директории назначения, если она не существует
Я хочу команду (или, возможно, опцию для cp), которая создает целевой каталог, если он не существует.
Пример:
cp -? файл /путь/к/копии/файла/по/очень/глубокому/пути
Как это можно реализовать?
5 ответ(ов)
Команда mkdir -p "$d" && cp file "$d"
выполняет две операции. Первое — это создание директории с помощью mkdir -p "$d"
, где -p
позволяет создать промежуточные директории, если они не существуют. Второе — это копирование файла с именем file
в созданную директорию $d
.
Важно отметить, что опция -p
для mkdir
позволяет избежать ошибок, если директория уже существует, в то время как для команды cp
такой опции нет. Если вы попытаетесь использовать cp file "$d"
, и директория $d
по каким-то причинам не существует, команда завершится неудачно с сообщением об ошибке. Таким образом, в этом случае использование конструкций с &&
позволяет сначала убедиться в успешном создании директории, прежде чем копировать туда файл.
Если оба из следующих условий верны:
- Вы используете GNU версию команды
cp
(а не, например, версию для Mac), и - Вы копируете из существующей структуры каталогов и просто хотите ее воссоздать,
то вы можете сделать это с помощью флага --parents
в команде cp
. В информационной странице (доступной по адресу http://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html#cp-invocation или с помощью info cp
или man cp
) указано:
--parents Формирует имя каждого файла назначения, добавляя к целевому каталогу слэш и указанное имя исходного файла. Последний аргумент, переданный `cp`, должен быть именем существующего каталога. Например, команда: cp --parents a/b/c existing_dir копирует файл `a/b/c` в `existing_dir/a/b/c`, создавая все отсутствующие промежуточные каталоги.
Пример использования:
/tmp $ mkdir foo
/tmp $ mkdir foo/foo
/tmp $ touch foo/foo/foo.txt
/tmp $ mkdir bar
/tmp $ cp --parents foo/foo/foo.txt bar
/tmp $ ls bar/foo/foo
foo.txt
Функция оболочки, которая выполняет то, что вам нужно, называется bury_copy
, потому что она создает каталог для файла, в который он будет помещен. Вот пример реализации:
bury_copy() { mkdir -p `dirname $2` && cp "$1" "$2"; }
Как это работает:
- mkdir -p
dirname $2
: Эта часть команды создает все необходимые каталоги для пути, указанного во втором аргументе.dirname
извлекает имя каталога из полного пути файла. - cp "$1" "$2": Затем происходит копирование файла, указанного в первом аргументе, в директорию, созданную на предыдущем шаге, под именем файла, указанным во втором аргументе.
Как использовать:
Вы можете использовать функцию следующим образом:
bury_copy /путь/к/исходному_файлу /путь/к/новой/директории/файл
Это удобно, если вы хотите гарантировать, что директория для копируемого файла существует, прежде чем выполнять операцию копирования.
Вот один из способов сделать это:
mkdir -p `dirname /path/to/copy/file/to/is/very/deep/there` \
&& cp -r file /path/to/copy/file/to/is/very/deep/there
Команда dirname
возвращает родительский каталог для указанного пути назначения. Использование mkdir -p \
dirname ...`` позволяет создать этот каталог, что гарантирует, что при выполнении команды cp -r
базовый каталог будет существовать.
Преимущество данного метода по сравнению с опцией --parents
заключается в том, что он работает в случаях, когда последний элемент в пути назначения — это имя файла.
Кроме того, этот способ будет работать и на OS X.
Это было сказано очень поздно, но, возможно, поможет новичку где-то. Если вам нужно АВТОМАТИЧЕСКИ создавать папки, rsync
будет вашим лучшим другом.
rsync /путь/к/исходному_файлу /путь/к/целевой_директории/которая_не_существует/
Что означает "2>&1"?
Как установить переменную на вывод команды в Bash?
Как запросить ввод Yes/No/Cancel в скрипте оболочки Linux?
Как сделать паузу в shell-скрипте на одну секунду перед продолжением?
Как использовать 'grep' для непрерывного потока?