8

to copy contents from a folder i've read , the use is:

cp -rfva ../foldersource/. ./

but this works too

cp -rfva ../foldersource/* ./

is there any difference?

by example if i want to delete a content from a folder with . :

rm -rf ../foldersource/.

i get the error:

rm:  rejet delete folder '.' or '..':

but with asterisk is ok

rm -rf ../foldersource/*

so, asterisk is better options that works anywhere ?

3 Answers 3

10

There is a fundamental difference between these two argument forms. And it's an important one to understand what is happening.

With ../foldersource/. the argument is passed unchanged to the command, whether it's cp or rm or something else. It's up to the command whether that trailing dot has special or unique semantics different from the standard Unix convention of simply pointing to the directory it resides in; both rm and cp seem to treat it as a special case.

With ../foldersource/* the argument is first expanded by the shell before the command is ever even executed and passed any arguments. Thus, rm never sees ../foldersource/*; it sees the expanded version ../foldersource/file1.ext ../foldersource/file2.ext ../foldersource/childfolder1 and so on. This is important because operating systems limit how many arguments can be passed to a command, usually only a few hundred.

5
  • 4
    It's up to the command whether that trailing dot makes any sense Um, the dot always links to the containing directory itself, so ../foldersource/. shouldn't be any different from stating ./foldersource/ and in fact its just a redundant way to state the same thing. No command tries to "make sense" of dot or double dot, since these are standard on Linux/Unix filesystems. rm simply rejects removing current working directory as jimmij stated in their answer. Also, note that you are using ./ in all of your examples while OP has ../ there. Somewhat of a (big) difference. Commented Jul 24, 2017 at 0:45
  • "cp -rfva ../foldersource/. ./ " is equivalent to "cp -rfva ../foldersource ./", i want to copy foldersource content, but not the folder root
    – stackdave
    Commented Jul 24, 2017 at 2:57
  • 1
    @Stackdave no, cp -rfva ../foldersource/. ./ is NOT equivalent to cp -rfva ../foldersource ./. The trailing /. is significant Commented Jul 24, 2017 at 6:39
  • 2
    While what this answer says is correct, it's missing a very important difference as mentioned in @roaima's answer: the /* variant does not (usually) copy files or directories beginning with .
    – Adam
    Commented Jul 24, 2017 at 10:03
  • @SergiyKolodyazhnyy You are right; the . is a standard convention in Unix to denote the current directly. Also, thank you for pointing out that I had used ./ in my examples when I should have used ../; I will fix that. You are incorrect about about whether commands "make sense" of the trailing dot; as the OP points out (and I have experienced with cp) both rm and cp behave differently when a trailing . is present. I should have written something like "it's up to the command if the trailing dot has special or unique semantics". I'll change my answer for clarity.
    – eestrada
    Commented Jul 24, 2017 at 23:57
10

When you copy using cp -a source/* target/ you are copying most of the files and directories from source to target. Specifically, the items that are excluded will probably be files beginning with a dot (.) in the top level of source.

Consider these files (or directories) in source

apple        # will be copied
banana/      # will be copied, as will all its contents
.cherry      # will not be copied

When you copy using cp -a source/. target/ you are copying the entire contents of source, including any items beginning with a dot (.) to target

Consider these files (or directories) in source

apple        # will be copied
banana/      # will be copied, as will all its contents
.cherry      # will be copied

If you're using bash, zsh, you can use the dotglob option to change the meaning of * so that it includes files and directories beginning with a dot (yash also has a dotglob option; however, it then includes . and .. in glob expansions which limits its usability. See also FIGNORE='@(.|..)' in ksh93).

Interestingly, cp -a source/. target/ is guaranteed never to create the component target/source. (On the other hand, cp -a source target/ will do one of two things depending on whether or not target already exists. See How to copy a folder recursively in an idempotent way using cp for the details.)


When you delete using rm -rf source/* you are deleting the files and directories within source that do not begin with a dot (.). Subject to the dotglob setting I've already mentioned. It will not delete the directory source itself.

When you try to delete using rm -rf source/. it will fail - as others have already explained - because POSIX prohibits deletion of a path whose last component is . or ... The closest equivalent is rm -rf source, which will delete the source directory and all its contents regardless of whether or not they begin with a dot (.).

1
7

You cannot do rm -rf ../foldersource/. because rm doesn't allow this, as explicitly stated in the manual:

Any attempt to remove a file whose last file name component is ‘.’ or ‘..’ is rejected without any prompting, as mandated by POSIX.

and in the POSIX manual man 1p rm we see:

If either of the files dot or dot-dot are specified as the basename portion of an operand (that is, the final pathname component) or if an operand resolves to the root directory, rm shall write a diagnostic message to standard error and do nothing more with such operands.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .