Когда я использую
cp -R inputFolder outputFolder
результат зависит от контекста :
- если
outputFolder
он не существует, он будет создан и путь клонированной папки будетoutputFolder
. - если
outputFolder
существует, то созданный клон будетoutputFolder/inputFolder
Это ужасно , потому что я хочу создать какой-нибудь сценарий установки, и если пользователь запустит его дважды по ошибке, он создаст outputFolder
первый раз, а затем при втором запуске все вещи будут созданы снова outputFolder/inputFolder
.
- Я хочу всегда первое поведение: создать клона рядом с оригиналом (в качестве родного брата).
- Я хочу использовать,
cp
чтобы быть портативным (например, MINGW неrsync
поставляется) - Я проверил,
cp -R --parents
но это воссоздает путь до дерева каталогов (так что клон не будет,outputFolder
ноsome/path/outputFolder
) --remove-destination
или--update
в случае 2 ничего не изменить, все же вещи копируются вoutputFolder/inputFolder
Есть ли способ сделать это без предварительной проверки на наличие outputFolder
(если папка не существует, то ...) или с помощью rm -rf outputFolder
?
Каков согласованный, переносимый способ UNIX сделать это?
mv
перемещение коллекции файлов в один обычный?rsync
?cp
, конвейерная передача между двумяtar
командами - хороший надежный способ копирования деревьев.rsync
отправлен.tar -C input -cf - . | tar -C output -xf -
работает.-C
меняет рабочий каталог, но это не стандартная опция, поэтому, если она не поддерживается, для начала вам нужно запустить два tars в правильных рабочих каталогах, например.( cd input && tar -cf - . ) | ( cd output && tar -xf - )
Однако, если вы имеете дело с Windows, я бы просто использовал ответ roaima.Ответы:
Используйте это вместо:
Это работает точно так же, как, скажем,
cp -R aaa/bbb ccc
работает: еслиccc
не существует, то он создается как копияbbb
и его содержимое; но если онccc
уже существует, онccc/bbb
создается как копияbbb
и его содержимое.Практически в любом случае
bbb
это приводит к нежелательному поведению, которое вы отметили в своем Вопросе. Тем не менее, в этой конкретной ситуацииbbb
это справедливо.
, так иaaa/bbb
естьaaa/.
, что, в свою очередь, действительно справедливо,aaa
но под другим именем. Итак, у нас есть два сценария:ccc
не существует:Команда
cp -R aaa/. ccc
означает «создаватьccc
и копировать содержимоеaaa/.
вccc/.
, т.е. копироватьaaa
вccc
.ccc
существует:Команда
cp -R aaa/. ccc
означает «скопировать содержимоеaaa/.
вccc/.
, т. Е. Скопироватьaaa
вccc
.источник
inputFolder/.
вместо,inputFolder
и это действительно работает для меня на Windows / Git Bash. (Это не работает, однако, только с трейлингом/
, мне нужна также точка после косой черты). Я дал +1, потому что это интересно, хотя, вероятно, это слишком сложно, чтобы использовать его в публичном коде :)Не копируйте папку, только скопируйте содержимое:
Таким образом, вы оба гарантируете, что целевой каталог создается при первом запуске скрипта, и избегаете проблемы при его запуске во второй раз.
Крис Даун очень правильно указывает, что в bash это будет пропускать файлы, имя которых начинается с a
.
. Чтобы избежать этого, вы можете запуститьshopt -s dotglob
перед запуском команды выше.И
-p
дляmkdir
и-R
дляcp
определяются POSIX , так это должно быть совершенно портативным.источник
.
. В Bash вы можете использоватьdotglob
для этого.Попробуйте
-T
вариантcp
. Это существует в GNU coreutilscp
версии 8.22; это не может быть портативным за пределами этого.источник
cp -T
(cp --no-target-directory
). unix.stackexchange.com/questions/94831/… К сожалению, моя версияcp
намного старше.-u
отличный вариант, чтобы сделать его ленивым.Вы также можете использовать
rsync
:(обратите внимание на косые черты, особенно после первого)
источник
На мой взгляд, нет ничего проще и портативнее, чем
rm -rf outputFolder
. Так что я всегда придерживаюсь этого. Я понимаю, что ваш вопрос отличается, но я думаю, что это лучшая практика.источник
cp
был одинаковым как в том случае, когда каталог не существует, так и в том случае, если он существует. Так о чем ты говоришь?cp
заданная OP, не сохраняет разрешения (или временные метки).Вы можете использовать
-t
опциюcp
команды как:теперь, если целевой папки не существует, она выдаст ошибку:
Команда note выше скопирует
inputFolder
вместе со своим содержимым (а не только с содержимым внутри него)если вы хотите скопировать только его содержимое,
inputFolder
это становится немного сложнее (поскольку вы должны быть осторожны при использовании глобализации оболочки при использовании звездочки *)теперь, если целевой папки не существует, она выдаст ошибку:
работает с
cp (GNU coreutils) 8.23
источник