Cuando uso
cp -R inputFolder outputFolder
el resultado depende del contexto :
- si
outputFolderno existe, se creará y se creará la ruta de la carpeta clonadaoutputFolder. - si
outputFolderexiste, entonces el clon creado seráoutputFolder/inputFolder
Esto es horrible , porque quiero crear un script de instalación, y si el usuario lo ejecuta dos veces por error, lo habrá outputFoldercreado la primera vez, luego, en la segunda ejecución, todo se creará nuevamente outputFolder/inputFolder.
- Siempre quiero el primer comportamiento: crear un clon al lado del original (como hermano).
- Quiero usar
cppara ser portátil (por ejemplo, MINGW no se harsyncenviado) - Lo comprobé
cp -R --parentspero esto recrea la ruta hasta el árbol de directorios (por lo que el clon no seráoutputFolderperosome/path/outputFolder) --remove-destinationo--updateen el caso 2 no cambia nada, aún las cosas se copian enoutputFolder/inputFolder
¿Hay alguna manera de hacer esto sin verificar primero la existencia de outputFolder(si la carpeta no existe, entonces ...) o usar rm -rf outputFolder?
¿Cuál es la forma acordada y portátil de UNIX de hacer eso?

mvmover una colección de archivos a una única normal?rsync?cp, canalizar entre dostarcomandos es una buena forma confiable de copiar árboles.rsyncenviado.tar -C input -cf - . | tar -C output -xf -funciona.-Ccambia el directorio de trabajo, pero no es una opción estándar, por lo que si no es compatible, debe comenzar a ejecutar los dos tars en los directorios de trabajo correctos, por ejemplo, sin( cd input && tar -cf - . ) | ( cd output && tar -xf - )embargo, si se trata de Windows, usaría la respuesta de Roaima.Respuestas:
Use esto en su lugar:
Esto funciona exactamente de la misma manera que, por ejemplo,
cp -R aaa/bbb cccfunciona: sicccno existe, entonces se crea como una copiabbby su contenido; pero sicccya existe,ccc/bbbse crea como la copiabbby sus contenidos.Para casi cualquier caso,
bbbesto da el comportamiento indeseable que anotó en su Pregunta. Sin embargo, en esta situación específica,bbbes justo., asíaaa/bbbes realmenteaaa/., que a su vez es realmente justoaaapero con otro nombre. Entonces tenemos estos dos escenarios:cccno existe:El comando
cp -R aaa/. cccsignifica "crearcccy copiar el contenido deaaa/.enccc/., es decir, copiaraaaenccc.cccexiste:El comando
cp -R aaa/. cccsignifica "copiar el contenido deaaa/.enccc/., es decir, copiaraaaenccc.fuente
inputFolder/.lugar deinputFoldery, de hecho, funciona para mí en Windows / Git Bash. (Sin embargo, no funciona solo con un final/, también necesito el punto después de la barra). Le di +1 porque es interesante, aunque probablemente sea un poco complicado usarlo en código público :)No copie la carpeta, solo copie el contenido:
De esta manera, ambos se aseguran de que el directorio de destino se cree la primera vez que se ejecuta el script y evitan el problema al ejecutarlo por segunda vez.
Chris Down señala muy correctamente que en bash, esto omitirá los archivos cuyo nombre comienza con a
.. Para evitar esto, puede ejecutarshopt -s dotglobantes de ejecutar el comando anterior.POSIX define tanto
-pparamkdircomo-Rparacp, por lo que debería ser perfectamente portátil.fuente
.. En bash, puedes usardotglobpara eso.Prueba la
-Topción decp. Esto existe en GNU coreutilscpversión 8.22; Puede que no sea portátil fuera de eso.fuente
cp -T(cp --no-target-directory). unix.stackexchange.com/questions/94831/… Lamentablemente, mi versión decpes mucho más antigua.-ues una gran opción para agregar para hacerlo perezoso.También puedes usar
rsync:(tenga en cuenta las barras, especialmente después de la primera)
fuente
En mi opinión, no hay nada más simple y más portátil que
rm -rf outputFolder. Entonces, siempre me quedo con eso. Entiendo que su pregunta es diferente, pero creo que esta es la mejor práctica.fuente
cpsea el mismo, tanto cuando el directorio no existe como cuando existe. ¿Entonces, de qué estás hablando?cpcomando dado por el OP no mantiene permisos (o marcas de tiempo).Puede usar la
-topción decpcomando como:ahora si la carpeta de destino no existe, arrojará un error:
Nota: el comando anterior se copiará
inputFolderjunto con su contenido (y no solo el contenido que contiene)si desea copiar solo el contenido del
inputFoldermismo se vuelve un poco complicado (ya que debe tener cuidado al usar el glob de shell mientras usa el asterisco *)ahora si la carpeta de destino no existe, arrojará un error:
funciona con
cp (GNU coreutils) 8.23fuente