¿Por qué "cp -ra/. b" se comporta como lo hace?

¿Por qué "cp -ra/. b" se comporta como lo hace?

Pensé eso ay a/.es el mismo camino. Sin embargo, he descubierto queCPysincronizacióncopie el contenido del directorio en lugar del directorio en sí cuando /.se agregue a la ruta de origen. También lo intenté a/inner/..; esto también funcionó.

$ cp -r a b  # Copies dir a into dir b.
$ cp -r a/. b  # Copies files from dir a into dir b.
$ cp -r a/inner/.. b  # Also copies files from dir a into dir b.
$ cd a && cp -r . ../b  # One more way to copy inner files.

Entiendo que esto es útil. Pero estoy un poco confundido porque parece que esta característica rompe los estándares.

¿Cómo funciona esto? ¿Está esta característica documentada en alguna parte? ¿Es esta una característica del sistema operativo?CPo golpe?

Respuesta1

Entiendo que esto es útil. Pero estoy un poco confundido porque parece que esta característica rompe los estándares.

CPEl comportamiento al copiar recursivamente de a/.a bes perfectamente consistente con su comportamiento "normal".

Por defecto,CP's no crea directorios principales. Esto se puede modificar con elpadrescambiar:

   --parents
          use full source file name under DIRECTORY

Pero ¿qué significa eso?

Significa que mientras el comando

cp --parents -r some/path/to/source dest

Copiará el contenido del directorio fuente en dest/some/path/to/source, el comando

cp -r some/path/to/source dest

Copiará el contenido del directorio fuente en dest/source.

Asimismo, el comando

cp -r some/path/to/source/. dest

Copiará el contenido del directorio fuente en dest/., que es solo dest.

Pensé ay a/.es el mismo camino.

aya/. esel mismo camino. Pero como argumento paraCP, es solo una cuerda.

Tenga en cuenta que los comandos

cp --parents -r some/path/to/source dest

y

cd some/path/to && cp --parents -r source dest

también se comportará de manera diferente.


Qué pasa cp -r a/inner/.. b? Teniendo en cuenta su explicación, ¿no debería copiar archivos b/..(es decir, al directorio actual)?

Bueno, sí. Esta es una excepción.

Al menos en la versión GNU deCP, existe un caso especial para el ..nombre base.

Decoreutils-8.22/src/cp.c:

          if (parents_option)
            {
              [removed]
            }
          else
            {
              char *arg_base;
              /* Append the last component of 'arg' to 'target_directory'.  */

              ASSIGN_BASENAME_STRDUPA (arg_base, arg);
              /* For 'cp -R source/.. dest', don't copy into 'dest/..'. */
              dst_name = (STREQ (arg_base, "..")
                          ? xstrdup (target_directory)
                          : file_name_concat (target_directory, arg_base,
                                              NULL));
            }

La motivación parece ser evitar copiar fuera de la carpeta de destino, lo cual, si bien es perfectamente coherente conCPEl comportamiento de en todos los demás casos es un poco contradictorio y podría tener consecuencias desagradables.

Después de todo, no creo que nadie esperara recibir el comando.

cp -r .. ~

para afectar archivos fuera de su directorio de inicio...

Respuesta2

$ mkdir a b a/inner
$ touch a/a{1..3} b/b{1..3}
$ ls -R
.:
a  b

./a:
a1  a2  a3  inner

./a/inner:

./b:
b1  b2  b3
$ cp a b
cp: omitting directory ‘a’
$ cp a/. b
cp: omitting directory ‘a/.’
$ cp a/inner/.. b
cp: omitting directory ‘a/inner/..’
$ cd a && cp . ../b
cp: omitting directory ‘.’
$ cd ..
$ ls -R
.:
a  b

./a:
a1  a2  a3  inner

./a/inner:

./b:
b1  b2  b3

Ninguna de las cosas que dices suceden, en realidad suceden. Los cuatro cpcomandos no hacen nada. Quizás tengas un alias para cpcargado. Puedes comprobar esto con alias cp.

Respuesta3

A propósito rsync(1), lea su manual.con cuidado. Utiliza algunas convenciones inusuales para referirse a "el contenido del directorio" frente a "el directorio y su contenido".

Para cp(1)y otros comandos de Linux, en elnúcleonivel ae a/.incluso a/inner/..hacer referencia exactamente al mismo directorio. Eso no significa que la aplicación no pueda analizarlos por sí misma y darles significados diferentes, pero es más fácil enviar la cadena al núcleo, quien hará lo correcto.

Respuesta4

Si no recuerdo mal, creo que . en este caso funciona de manera similar a un archivo *. En esencia, un carácter comodín.

información relacionada