Cuando uso
cp -R inputFolder outputFolder
el resultado depende del contexto :
- si
outputFolder
no existe, se creará y se creará la ruta de la carpeta clonadaoutputFolder
. - si
outputFolder
existe, 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á outputFolder
creado 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
cp
para ser portátil (por ejemplo, MINGW no se harsync
enviado) - Lo comprobé
cp -R --parents
pero esto recrea la ruta hasta el árbol de directorios (por lo que el clon no seráoutputFolder
perosome/path/outputFolder
) --remove-destination
o--update
en 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?
mv
mover una colección de archivos a una única normal?rsync
?cp
, canalizar entre dostar
comandos es una buena forma confiable de copiar árboles.rsync
enviado.tar -C input -cf - . | tar -C output -xf -
funciona.-C
cambia 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 ccc
funciona: siccc
no existe, entonces se crea como una copiabbb
y su contenido; pero siccc
ya existe,ccc/bbb
se crea como la copiabbb
y sus contenidos.Para casi cualquier caso,
bbb
esto da el comportamiento indeseable que anotó en su Pregunta. Sin embargo, en esta situación específica,bbb
es justo.
, asíaaa/bbb
es realmenteaaa/.
, que a su vez es realmente justoaaa
pero con otro nombre. Entonces tenemos estos dos escenarios:ccc
no existe:El comando
cp -R aaa/. ccc
significa "crearccc
y copiar el contenido deaaa/.
enccc/.
, es decir, copiaraaa
enccc
.ccc
existe:El comando
cp -R aaa/. ccc
significa "copiar el contenido deaaa/.
enccc/.
, es decir, copiaraaa
enccc
.fuente
inputFolder/.
lugar deinputFolder
y, 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 dotglob
antes de ejecutar el comando anterior.POSIX define tanto
-p
paramkdir
como-R
paracp
, por lo que debería ser perfectamente portátil.fuente
.
. En bash, puedes usardotglob
para eso.Prueba la
-T
opción decp
. Esto existe en GNU coreutilscp
versió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 decp
es mucho más antigua.-u
es 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
cp
sea el mismo, tanto cuando el directorio no existe como cuando existe. ¿Entonces, de qué estás hablando?cp
comando dado por el OP no mantiene permisos (o marcas de tiempo).Puede usar la
-t
opción decp
comando como:ahora si la carpeta de destino no existe, arrojará un error:
Nota: el comando anterior se copiará
inputFolder
junto con su contenido (y no solo el contenido que contiene)si desea copiar solo el contenido del
inputFolder
mismo 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.23
fuente