LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 10-14-2012, 08:40 AM   #16
porphyry5
Member
 
Registered: Jul 2010
Location: oregon usa
Distribution: Slackware 14.1, Arch
Posts: 421

Rep: Reputation: 18

Quote:
Originally Posted by suicidaleggroll View Post
d) more than two names passed, last one is an existing directory

The results will be:

d) the first N-1 files/dirs are copied INTO the last directory
Thanks for the explanation. What confused me is that situation d) might lead one to think that the last named item forms the destination, all preceding items form the sources. But that is not necessarily what cp does. Because literally what cp does in the situation below is use ALL named items as sources, and copy ALL files found therein to the lowest level subdirectory available in the last named item. That is, besides copying the 3 files from d1, it also copies the 2 files from top level of d2, so 5 files result in d2/sd3.
Code:
~ $ mkdir d1 d2
~ $ > d1/fa
~ $ > d1/fb
~ $ > d1/fc
~ $ > d2/fd
~ $ > d2/fe
~ $ mkdir d2/sd3
~ $ ls d1 d2
d1:
fa  fb  fc

d2:
fd  fe  sd3/
~ $ cp d1/* d2/*
~ $ ls d2/sd3
fa  fb  fc  fd  fe
~ $ ls d2
fd  fe  sd3/
So cp expands all the named items into a list of possibilities, flags and removes any that are invalid, and the final item in the expanded list is the destination.

Last edited by porphyry5; 10-14-2012 at 08:52 AM. Reason: add conclusion
 
Old 10-14-2012, 10:23 AM   #17
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Quote:
Originally Posted by porphyry5 View Post
So cp expands all the named items into a list of possibilities, flags and removes any that are invalid, and the final item in the expanded list is the destination.
Except that it's not cp expanding the globs, it's the shell doing it, before the program is even run. cp never sees the globbing pattern at all.

(Unless the glob fails to match anything that is, in which case cp will receive the literal text string as an argument, try to treat it as a filename, and give you a "no such file or directory" error for it.)

In your example, the final command generated and executed by the shell for this:
Code:
cp d1/* d2/*
...is this:
Code:
cp d1/fa d1/fb d1/fc d2/fd d2/fe d2/sd3
And so all the files go into d2/sd3, because it's the final argument in the executed command, and it's a directory (a valid target).


Again, if you ever want to see the actual command that would be executed after the shell is done parsing the line, just stick an "echo" on the front of it.
 
1 members found this post helpful.
Old 10-14-2012, 10:36 AM   #18
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
As an additional illustration, let's try changing the name of the final target directory:
Code:
$ mkdir d{1,2,2/d3}
$ touch d1/f{a..c} d2/f{d,e}
$ tree
.
├── d1
│** ├── fa
│** ├── fb
│** └── fc
└── d2
    ├── d3
    ├── fd
    └── fe

3 directories, 5 files
Now let's check our command. I'll use a slightly more sophisticated globbing pattern that expands to the same thing as before.
Code:
$ echo cp d[1-2]/*
cp d1/fa d1/fb d1/fc d2/d3 d2/fd d2/fe
Uh-oh, looks like trouble!
Let's see what happens when we actually execute it:

Code:
$ cp d[1-2]/*
cp: target `d2/fe' is not a directory
Yep, the renamed directory sorted differently, and so the final argument was not a directory.
 
2 members found this post helpful.
Old 10-14-2012, 01:47 PM   #19
eNux eLin
LQ Newbie
 
Registered: Oct 2012
Posts: 9

Original Poster
Rep: Reputation: Disabled
My instructor says this is way past the scope of our Intro OS Class LOL

I had to push the envelope though since I was so confused by your answers that it intrigued me.

Quote:
cp –r /home/UserName/a/* /home/UserName/b/*
The second asterisk seems to cause a duality role for the last argument making it both a source and a destination string. Also, the second asterisk (in combination with -r)appears to send the cp files to only the highest aphabetical named subdirectory from both the source and also the parent target directory.

Is there any way to control the actual target subdirectory other than by naming? or send all the source files to all destination subdirectories?

My very first script (this one is for testing the second asterisk):

Quote:
mkdir /home/UserName/c /home/UserName/a
mkdir /home/UserName/a/aSubDir1
mkdir /home/UserName/a/aSubDir2
mkdir /home/UserName/a/aSubDir3
mkdir /home/UserName/c/cSubDir1
mkdir /home/UserName/c/cSubDir2
mkdir /home/UserName/c/cSubDir3
touch /home/UserName/a/aFile1
touch /home/UserName/a/aFile2
touch /home/UserName/a/aFile3
touch /home/UserName/c/cFile1
touch /home/UserName/c/cFile2
touch /home/UserName/c/cFile3
mkdir /home/UserName/b
mkdir /home/UserName/b/bSubDir1
mkdir /home/UserName/b/bSubDir3
touch /home/UserName/b/bFile1
touch /home/UserName/b/bFile3
touch /home/UserName/a/aSubDir1/aSubDirFile1
touch /home/UserName/a/aSubDir2/aSubDirFile2
touch /home/UserName/a/aSubDir3/aSubDirFile3
touch /home/UserName/c/cSubDir1/cSubDirFile1
touch /home/UserName/c/cSubDir2/cSubDirFile2
touch /home/UserName/c/cSubDir3/cSubDirFile3
touch /home/UserName/b/bSubDir1/bSubDirFile1
touch /home/UserName/b/bSubDir3/bSubDirFile3
mkdir /home/UserName/b/bSubDir2
touch /home/UserName/b/bfile2
touch /home/UserName/b/bSubDir2/bSubDirFile2
cd /home/UserName/c
cp –r /home/UserName/a/* /home/UserName/b/*
Thanks everyone, I'll be pleased to read more of your inciteful comments

Last edited by eNux eLin; 10-14-2012 at 01:49 PM.
 
Old 10-14-2012, 01:55 PM   #20
suicidaleggroll
Senior Member
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 2,830

Rep: Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001
Quote:
Originally Posted by eNux eLin View Post
The second asterisk seems to cause a duality role for the last argument making it both a source and a destination string. Also, the second asterisk (in combination with -r)appears to send the cp files to only the highest aphabetical named subdirectory from both the source and also the parent target directory.
I think you're making this more complicated than it really is. cp doesn't do anything with the asterisk. The asterisk is expanded by the shell before cp is even called. As far as cp is concerned, it just received a long list of files/dirs, and it copies the first N-1 files/dirs into the last one. cp has no idea if you typed all of those file names out by hand or if you used a globbing pattern to match them.

When you use globbing patterns like this, there is no "first argument" or "second argument" in what you type. The first argument, second argument, etc., that matter are the ones received by cp, AFTER expansion by the shell. cp can't tell the difference between two files that you typed on the command line versus two files that were matched by a globbing pattern.
 
2 members found this post helpful.
Old 10-14-2012, 03:08 PM   #21
eNux eLin
LQ Newbie
 
Registered: Oct 2012
Posts: 9

Original Poster
Rep: Reputation: Disabled
Its an order of opeartions thing then

Only AFTER the expansion is the last CP argument considered for the destanation role . . . and all the other expanded arguments are then used as sources regardless of their origin. I hope this is correct because it is finally makes sense to me what is occuring. Expansion just creates one long list of equals . . . except for the last argument. Too bad you don't find this in "man cp" so that a rooky doesn't post these questions . . . LOL

The old IBM PC DOS slowly dies in my mind
 
Old 10-14-2012, 03:23 PM   #22
eNux eLin
LQ Newbie
 
Registered: Oct 2012
Posts: 9

Original Poster
Rep: Reputation: Disabled
Wow I learned a bunch of new terms and concepts . . . thanks all
 
Old 10-14-2012, 04:19 PM   #23
suicidaleggroll
Senior Member
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 2,830

Rep: Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001Reputation: 1001
Quote:
Originally Posted by eNux eLin View Post
Its an order of opeartions thing then

Only AFTER the expansion is the last CP argument considered for the destanation role . . . and all the other expanded arguments are then used as sources regardless of their origin. I hope this is correct because it is finally makes sense to me what is occuring. Expansion just creates one long list of equals . . . except for the last argument.
That's exactly right.
 
Old 10-14-2012, 09:21 PM   #24
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 1,436

Rep: Reputation: 599Reputation: 599Reputation: 599Reputation: 599Reputation: 599Reputation: 599
Quote:
Originally Posted by eNux eLin View Post
Is there any way to control the actual target subdirectory other than by naming? or send all the source files to all destination subdirectories?
"Other than by naming"??? Well, I don't know how you'd specify a target other than by naming it, but one of the options for cp is "--target-directory=some_directory" (short form, "-t some_directory"). When you specify the destination that way, all of the other non-flag arguments are treated as sources. You should still be careful that none of your glob patterns match your designated target, but cp is pretty good about detecting when the destination is the same as the source. That option is mainly useful when you are building up a source argument list with a script or a program like find or xargs that wants to add arguments at the end of the list.
Code:
cp --target-directory=d3 d1/* d2/*
cp -t d3 d1/* d2/*
Use of glob patterns for that target directory is highly discouraged.
 
1 members found this post helpful.
Old 10-15-2012, 01:00 AM   #25
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
I don't know what your instructor is thinking. Globbing is one of the most basic foundational features of the shell, and should be taught right from the beginning. Anyone who doesn't know how to glob doesn't really know the shell.

Globbing is at its heart just simple pattern matching and substitution; a shell shortcut that lets you avoid typing every file argument manually, and I don't see any way to cover it more simply than we have already. It works in exactly the same way with all commands, happening before anything is executed, and it's up to the command used to interpret the final argument list it produces.


Of course, if you noticed, I already mentioned the -t option to cp and mv in my first post above. The only minor drawback with that can be that if you use a string like "cp -t d2/d3 d1/* d2/*", the target directory will also be part of the globbing expansion, and you'll end up telling the program to move the directory into itself. But since cp/mv won't let you do that anyway, it doesn't cause any actual harm, just another error message.

Amusingly, if you did try to use a globbing pattern in -t, then if the first expanded entry happens to be a directory you'll end up moving everything there, in the reverse of what we've demonstrated up to now.
 
1 members found this post helpful.
Old 10-15-2012, 10:04 AM   #26
porphyry5
Member
 
Registered: Jul 2010
Location: oregon usa
Distribution: Slackware 14.1, Arch
Posts: 421

Rep: Reputation: 18
Quote:
Originally Posted by David the H. View Post
Except that it's not cp expanding the globs, it's the shell doing it, before the program is even run. cp never sees the globbing pattern at all.

...

Again, if you ever want to see the actual command that would be executed after the shell is done parsing the line, just stick an "echo" on the front of it.
Thank you for the reminder. I really have to get out of this pernicious habit of thinking of commands as single processes.
 
Old 10-15-2012, 10:23 AM   #27
porphyry5
Member
 
Registered: Jul 2010
Location: oregon usa
Distribution: Slackware 14.1, Arch
Posts: 421

Rep: Reputation: 18
Quote:
Originally Posted by David the H. View Post
As an additional illustration, let's try changing the name of the final target directory:
Code:
$ mkdir d{1,2,2/d3}
$ touch d1/f{a..c} d2/f{d,e}
$ tree
.
├── d1
│** ├── fa
│** ├── fb
│** └── fc
└── d2
    ├── d3
    ├── fd
    └── fe

3 directories, 5 files
Now let's check our command. I'll use a slightly more sophisticated globbing pattern that expands to the same thing as before.
Code:
$ echo cp d[1-2]/*
cp d1/fa d1/fb d1/fc d2/d3 d2/fd d2/fe
Uh-oh, looks like trouble!
Let's see what happens when we actually execute it:

Code:
$ cp d[1-2]/*
cp: target `d2/fe' is not a directory
Yep, the renamed directory sorted differently, and so the final argument was not a directory.
Thank you, this is a really informative post, refinements of mkdir and touch I was unaware of; a shortcut method of writing globs that will probably lead me to using file and directory names as cryptic as the variable names I favor; tree, a command new to me; and that the generated list is sorted.
 
Old 10-20-2012, 07:50 AM   #28
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
I should've mentioned that my mkdir/touch commands above aren't using globbing, but brace expansion, which is a completely different feature, although it can often be used in a similar way.

The main difference between the two is that globbing is a matching language, and will only expand if there are filenames that match the pattern (or return a true condition in string matching in case statements or the like), while brace expansion always produces a series of entries, whether or not anything matches.

In other words, brace expansion should be used when you want to create lists of things, while globbing should be used when you want to match things that already exist.
 
  


Reply

Tags
asterisk, path, wildcard


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] cp: Create any directories necessary to open the destination path entz Linux - Software 10 01-10-2012 05:12 AM
Find command to search wildcard in path? markdjones82 Linux - General 12 12-11-2009 01:02 AM
get soft link destination path frado Linux - Software 5 05-19-2007 06:05 PM
how to unzip all files with a wildcard path? adamrosspayne Linux - Newbie 12 06-20-2006 01:16 PM
Kmail links open to wrong destination path tigerflag Slackware 2 12-30-2003 10:43 PM


All times are GMT -5. The time now is 03:43 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration