Subject: bug#20603: Possible bug in cp

From: Chris Puttick <[email-masked]>
Date: Tue, 19 May 2015 06:21:03 +0100

The expansion & consequences of my typo understood! However, given the
risks inherent in this edge case (directory only has 2 files in it)
and the unlikelihood of someone wanting to change a directory
containing 2 different files into a directory containing 2 identical
but differently named files, it would be great if the cp command to
check, when the source and destination directories are the same, the
file count in that directory and issue a warning before continuing if
the file count =2.

I guess this would apply to others where the consequences of a similar
typo would be bad, like mv.

On 19 May 2015 at 00:24, Bob Proulx <[email-masked]> wrote:
> Chris Puttick wrote:
>> In moment of tiredness issued a cp command similar to
>> cp /path/to/files/*
>> neglecting to add a destination (should have been ./)
>> The files in the directory were 2 vdisks both ending .qcow2.
>
> Ouch!  I am sorry for your loss.  I hope you had backups. :-(
>
>> No error message was generated and the apparent result of running the
>> command is that the file whose name came first alphabetically was
>> copied over the other.
>
> There was no error message because as far as the computer was
> concerned it did exactly as you instructed it and no error occurred.
>
> You are apparently not aware that the shell reads your command line,
> parses it, expands it, and then the shell executes the resulting
> command.  Many command line characters are "shell metacharacters".
> Search for that and you will find many references.  When I say shell
> here I will assume the bash shell however this part applies to all of
> the Unix-like command line shells such as ksh, zsh, csh, sh and so forth.
>
> One of the file glob characters is the "*" character.  (It is called a
> file glob because the star is expanded to match a glob of files.)
> Whenever you use a '*' in a command line that is an instruction to the
> shell.  It tells the shell to list the files and match them and
> replace the star character with the list of matching file names.  Try
> this exercise to understand a little bit about the '*' character and
> what the shell does.
>
>   $ mkdir /tmp/junk
>   $ cd /tmp/junk
>   $ touch file1
>   $ echo *
>   file1
>   $ touch file2
>   $ echo *
>   file1 file2
>   $ touch file 3
>   $ echo *
>   file1 file2 file3
>   $ echo *1
>   file1
>   $ echo *[23]
>   file2 file3
>
> As you can see the shell is replacing the '*' character with the files
> that were expanded which match it.  And I threw in another couple of
> file expansions too just to help push the concept home.
>
> By this point you should know that your cp command had a '*' in the
> command line.  The shell expanded that star.  There were only two
> expansions.  Therefore the shell invoked cp with two arguments.
>
>   cp /path/to/files/file1 /path/to/files/file2
>
> That is the command that cp was invoked with after the shell expanded
> the file globs on the command line.  As far as the cp command is
> concerned it was given a command, cp executed the command, and the
> command was completed without error.
>
> The cp command has no way of knowing that you wanted to execute this
> command instead.
>
>   cp /path/to/files/file1 /path/to/files/file2 ./
>
> How could it?  It can't.  One command looks just the same as the other
> one to the cp command.  None of the commands ever see the '*'
> character because it is expanded by the shell and replaced before the
> utility is invoked.
>
> Hope that expansion helps explain things.
>
> Bob

-- 
@putt1ck
putt1ck.blogspot.com
http://twoten.is
skype: putt1ck

Opinions in this email are my own and may not reflect that of my
clients, past employers, associates, friends, family, pets etc..