Как заставить команду cp создавать любые необходимые папки для копирования файла в место назначения [duplicate]

304

При копировании файла с помощью cp в папку, которая может или не может существовать, как мне получить cp, чтобы создать папку, если это необходимо? Вот что я пробовал:

[root@file nutch-0.9]# cp -f urls-resume /nosuchdirectory/hi.txt
cp: cannot create regular file `/nosuchdirectory/hi.txt': No such file or directory
  • 1
    @nelaar Возраст вопроса второстепенный; качество и широта ответов должны быть решающим фактором. У меня нет сильных предпочтений в любом случае, но я не думаю, что на данный момент стоит потратить усилия на то, чтобы изменить дублирующиеся отношения. Если вы думаете иначе, пожалуйста, предложите обоснование (возможно, на meta.stackoverflow.com для правильной видимости и процесса).
  • 0
    Искал то же самое и не смог найти мой ответ ниже, поэтому опубликую, как я в итоге сделал это: dirname "/nosuchdirectory/hi.txt" | while read path;do mkdir -p "$path"; done && cp -f urls-resume /nosuchdirectory/hi.txt
Показать ещё 1 комментарий
Теги:
cp

10 ответов

255

Если выполняется одно из следующих условий:

  • Вы используете версию GNU cp (а не, например, версию Mac), и
  • Вы копируете какую-либо существующую структуру каталогов, и вам просто нужно ее воссоздать

то вы можете сделать это с помощью флага --parents cp. На информационной странице (можно просмотреть http://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html#cp-invocation или с помощью info cp или man cp):

--parents
     Form the name of each destination file by appending to the target
     directory a slash and the specified name of the source file.  The
     last argument given to `cp' must be the name of an existing
     directory.  For example, the command:

          cp --parents a/b/c existing_dir

     copies the file `a/b/c' to `existing_dir/a/b/c', creating any
     missing intermediate directories.

Пример:

/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
146

Чтобы расширить христианский ответ, единственным надежным способом сделать это было бы объединение mkdir и cp:

mkdir -p /foo/bar && cp myfile "$_"

В стороне, когда вам нужно создать только один каталог в существующей иерархии, rsync может сделать это за одну операцию. Фактически я являюсь поклонником rsync как гораздо более универсальной замены cp:

rsync -a myfile /foo/bar/ # works if /foo exists but /foo/bar doesn't.  bar is created.
  • 4
    Это упомянуто в ответе выше, но я бы хотел еще раз подчеркнуть его (после нескольких минут, потраченных впустую из-за того, что не заметил мелкий шрифт): приведенная выше команда rsync не эквивалентна приведенной выше команде mkdir/cp . Он просто создает один уровень папки. На самом деле я не уверен, когда это может быть полезно.
  • 3
    Этот ответ является лучшим, потому что, если вы застряли с предыдущей командой cp, набранной перед поиском в Google, вы можете легко ctrl + a чтобы перейти к началу вашей непродуманной команды cp и исправить ее. Спасибо!
Показать ещё 5 комментариев
75

Я не знал, что вы можете сделать это с помощью cp.

Вы можете сделать это с помощью mkdir..

mkdir -p /var/path/to/your/dir

ИЗМЕНИТЬ См. Lhunath answer для включения cp.

  • 41
    CP (1) нет. mkdir -p / foo / bar && cp myfile "$ _" действительно единственный способ сделать это надежно.
  • 2
    Комментарий Луната - самый правильный и полный ответ
Показать ещё 7 комментариев
19

Для тех, кто находится на Mac OSX, возможно, самый простой способ обойти это - использовать ditto (только на Mac, AFAIK, хотя). Он создаст структуру каталогов, которая отсутствует в месте назначения.

Например, я сделал это

ditto 6.3.2/6.3.2/macosx/bin/mybinary ~/work/binaries/macosx/6.3.2/

где ~/work не содержал каталог двоичных файлов, прежде чем я запустил команду.

Я думал, что rsync должен работать аналогично, но, похоже, он работает только для одного уровня недостающих каталогов. То есть

rsync 6.3.3/6.3.3/macosx/bin/mybinary ~/work/binaries/macosx/6.3.3/

работал, потому что ~/work/binaries/macosx существовал, но не ~/work/binaries/macosx/6.3.2/

  • 1
    Мне это нравится, но проблема в том, что вы застрянете в среде, отличной от Mac. Вероятно, лучше всего изучить независимый от платформы подход. Также обратите внимание, что я считаю, что rsync может создавать каталоги с помощью флагов -avR.
14
 mkdir -p `dirname /nosuchdirectory/hi.txt` && cp -r urls-resume /nosuchdirectory/hi.txt
13

Можно также использовать команду find:

find ./ -depth -print | cpio -pvd newdirpathname
12

Такого варианта нет. Что вы можете сделать, так это запустить mkdir -p перед копированием файла

Я сделал очень классный script, который вы можете использовать для копирования файлов в местах, которые не существуют

#!/bin/bash
if [ ! -d "$2" ]; then
    mkdir -p "$2"
fi
cp -R "$1" "$2"

Теперь просто сохраните его, дайте ему разрешения и запустите его, используя

./cp-improved SOURCE DEST

Я ставлю параметр -R, но это просто черновик, я знаю, что это может быть, и вы улучшите его разными способами. Надеюсь, это поможет вам.

  • 3
    Пожалуйста, укажите ваши расширения параметров. Или вы будете страдать от ошибок, связанных с разделением слов и расширением пути. Поместите "" вокруг всех ваших $ foo's.
  • 8
    Это приведет к странным результатам, если кто-то попытается переименовать файл во время копирования: cp-improved /foo/file.jpg /bar/file.jpg.bak . Я /bar/file.jpg.bak/file.jpg с /bar/file.jpg.bak/file.jpg независимо от того, существует bar или нет
3

rsync - это работа!

#file:
rsync -aqz _vimrc ~/.vimrc

#directory:
rsync -aqz _vim/ ~/.vim
-4
cp -Rvn /source/path/* /destination/path/
cp: /destination/path/any.zip: No such file or directory

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

Момент назад я видел xxxxxxxx: Нет такого файла или каталога, потому что у меня закончилось свободное пространство. без сообщения об ошибке.

с такой же точностью:

ditto -V /source/path/* /destination/path
ditto: /destination/path/any.zip: No space left on device

после освобождения пространства cp -Rvn /source/path/* /destination/path/ работает как ожидалось

  • 0
    -6 ... Никто не хочет голосовать за Педро?
-14

Удивительно, но я не вижу правильного ответа в этой теме, просто используйте:

cp -r /foo/bar/baz /tmp

Как обычно, достаточно простого совета RTFM, выше будет скопировать файл baz в /tmp и под подкаталогами foo/bar (они будут созданы, если они не существуют)

cp --help
-R, -r, --recursive          copy directories recursively

Ещё вопросы

Сообщество Overcoder
Наверх
Меню