Por que "cp -ra/. b" se comporta dessa maneira?

Por que "cp -ra/. b" se comporta dessa maneira?

Eu pensei isso ae a/.é o mesmo caminho. No entanto, descobri queCPesincronizar novamentecopie o conteúdo do diretório em vez do próprio diretório quando /.for adicionado ao caminho de origem. Eu também tentei a/inner/..; isso também funcionou.

$ 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.

Eu entendo que isso é útil. Mas estou um pouco confuso porque parece que esse recurso quebra os padrões.

Como é que isso funciona? Esse recurso está documentado em algum lugar? Este é um recurso do sistema operacional,CPou festa?

Responder1

Eu entendo que isso é útil. Mas estou um pouco confuso porque parece que esse recurso quebra os padrões.

CPo comportamento ao copiar recursivamente de a/.para bé perfeitamente consistente com seu comportamento "normal".

Por padrão,CP's não cria diretórios pais. Isto pode ser modificado com opaistrocar:

   --parents
          use full source file name under DIRECTORY

Mas o que isso significa?

Isso significa que enquanto o comando

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

copiará o conteúdo do diretório de origem para dest/some/path/to/sourceo comando

cp -r some/path/to/source dest

copiará o conteúdo do diretório de origem para dest/source.

Da mesma forma, o comando

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

copiará o conteúdo do diretório de origem para dest/., que é apenas dest.

Eu pensei ae a/.é o mesmo caminho.

aea/. éo mesmo caminho. Mas como argumento paraCP, é apenas uma string.

Observe que os comandos

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

e

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

também se comportará de maneira diferente.


A respeito cp -r a/inner/.. b? Levando em consideração sua explicação, ele não deveria copiar os arquivos b/..(ou seja, para o diretório atual)?

Bem, sim. Esta é uma exceção.

Pelo menos na versão GNU doCP, há um caso especial para o ..nome 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));
            }

A motivação parece ser evitar copiar fora da pasta de destino, o que – embora perfeitamente consistente comCPo comportamento de em todos os outros casos – é um pouco contra-intuitivo e pode ter consequências desagradáveis.

Afinal, não acho que alguém esperaria o comando

cp -r .. ~

para afetar arquivos fora de seu diretório pessoal...

Responder2

$ 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

Nenhuma das coisas que você diz acontece, realmente acontece. Os quatro cpcomandos não fazem nada. Talvez você tenha um alias para cpcarregado. Você pode verificar isso com alias cp.

Responder3

A propósito rsync(1), leia seu manualcom cuidado. Ele usa algumas convenções incomuns para significar "o conteúdo do diretório" versus "o diretório e seu conteúdo".

Para cp(1)e outros comandos do Linux, nonúcleonível ae a/.até mesmo a/inner/..referem-se exatamente ao mesmo diretório. Isso não significa que o aplicativo não possa analisá-los por si mesmo e dar-lhes significados diferentes, mas é mais fácil simplesmente enviar a string para o kernel, que fará a coisa certa.

Responder4

Se bem me lembro, acredito no . neste caso funciona de forma semelhante a um arquivo *. Em essência, um caractere curinga.

informação relacionada