為什麼「cp -ra/.b」會有這樣的行為?

為什麼「cp -ra/.b」會有這樣的行為?

我以為aa/.是同一條路。然而,我發現CP同步/.新增到來源路徑時複製目錄內容而不是目錄本身。我也嘗試過a/inner/..;這也達到了目的。

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

我明白這很有用。但我有點困惑,因為這個功能似乎違反了標準。

這是如何運作的?此功能是否記錄在某處?這是作業系統的功能嗎?CP還是bash?

答案1

我明白這很有用。但我有點困惑,因為這個功能似乎違反了標準。

CPa/.從到遞歸複製時的行為b與其「正常」行為完全一致。

預設情況下,CP's 不建立父目錄。這可以透過以下方式修改父母轉變:

   --parents
          use full source file name under DIRECTORY

但是,這是什麼意思?

這意味著雖然命令

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

將把來源目錄的內容複製到dest/some/path/to/source指令中

cp -r some/path/to/source dest

會將來源目錄的內容複製到dest/source.

同樣,命令

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

會將來源目錄的內容複製到dest/.,這只是dest.

我想aa/.是同一條路。

aa/. 相同的路徑。但作為一個論據CP,它只是一個字串。

請注意這些命令

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

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

也會有不同的行為。


關於什麼cp -r a/inner/.. b?考慮到您的解釋,它不應該將檔案複製到b/..(即當前目錄)嗎?

嗯,是。這是一個例外。

至少在 GNU 版本中CP,基名有一個特殊情況..

coreutils-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));
            }

動機似乎是避免在目標資料夾之外複製,這雖然與CP在其他情況下的行為有點違反直覺,並且可能會產生令人不快的後果。

畢竟,我認為沒有人會期待這個命令

cp -r .. ~

影響他的主目錄之外的文件...

答案2

$ 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

你所說的事情都沒有發生,實際上沒有發生。這四個cp命令什麼都不做。也許您有一個已載入的別名cp。您可以使用 檢查這一點alias cp

答案3

順便rsync(1),閱讀它的手冊小心。它使用一些不尋常的約定來表示“目錄的內容”與“目錄及其內容”。

對於cp(1)其他 Linux 命令,請訪問核心levela甚至a/.引用a/inner/..完全相同的目錄。這並不意味著應用程式無法自行解析它們並賦予它們不同的含義,但將字串發送到核心會更容易,核心會做正確的事情。

答案4

如果沒記錯的話我相信。在這種情況下,其工作方式類似於 *.本質上是一個通配符。

相關內容