LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
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 03-31-2012, 04:14 AM   #1
matrix13
Member
 
Registered: Nov 2006
Location: Kerala, India
Distribution: Arch Linux
Posts: 134

Rep: Reputation: 25
Find image files and copy it to a common directory failed


I am using ubuntu 11.10.

I have a directory containing lot a directories and many of these directories contain several image files, both in jpg and png formats. Some directories are empty also. There might be a total of 100 files. I am trying to copy all these image files and put it in a common directory. I used the following command.

Code:
find /my/source/directory/ -iname *.jpg -exec cp {} /my/destination/directory/ \;
But this didn't copy all the files of type jpg. It only copied 6 files to be exact. So, what modification should be done in the command to copy all the files.

Also, what should I do if I want to copy both *.jpg and *.png in one go.

Thanks.
 
Old 03-31-2012, 04:25 AM   #2
kbp
Senior Member
 
Registered: Aug 2009
Posts: 3,790

Rep: Reputation: 653Reputation: 653Reputation: 653Reputation: 653Reputation: 653Reputation: 653
Maybe you don't have permissions in some of the directories .. ?

Code:
find /my/source/directory/ \( -iname *.jpg -o -iname *.png \) -exec cp {} /my/destination/directory/ \;

Last edited by kbp; 03-31-2012 at 04:45 AM. Reason: Example needed parens
 
Old 03-31-2012, 04:37 AM   #3
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Were there any error messages? If so, what were they.

To copy (or not!) .png files too:
Code:
find /my/source/directory/ -iname *.jpg -o -iname *.png -exec cp {} /my/destination/directory/ \;
EDIT: but safer to quote the patterns to ensure bash doesn't expand them to match any .jpg or .png files in the current directory:
Code:
find /my/source/directory/ -iname '*.jpg" -o -iname '*.png' -exec cp {} /my/destination/directory/ \;

Last edited by catkin; 03-31-2012 at 04:39 AM.
 
Old 03-31-2012, 04:46 AM   #4
kbp
Senior Member
 
Registered: Aug 2009
Posts: 3,790

Rep: Reputation: 653Reputation: 653Reputation: 653Reputation: 653Reputation: 653Reputation: 653
I did the same as you catkin but it actually needs parentheses
 
Old 03-31-2012, 05:12 AM   #5
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
You need to quote arguments that use wildcards. Otherwise they will expand to what *.jpg or *.png files are in the current directory, before the command is run.
Code:
set find ./ -iname *.pdf
:~/Documents/pdfs> echo ${*}
find ./ -iname 7007887b.pdf  AIMagzine-DeepQA.pdf at.pdf avr-libc-user-manual-1.0.4.pdf BLUEBOOK.pdf Converting movies to .mp4 with VLC media player.pdf credentials.pdf manual3.pdf

Last edited by jschiwal; 03-31-2012 at 05:14 AM.
 
Old 03-31-2012, 05:32 AM   #6
matrix13
Member
 
Registered: Nov 2006
Location: Kerala, India
Distribution: Arch Linux
Posts: 134

Original Poster
Rep: Reputation: 25
Thank you all for the explanations.

I tried with quotes also. Still not working. I am only able to copy a few files.

@kbp: I do have permission in all the directories. I even did a chmod on the parent directory. If I do the first part only, that is the "find" part, the terminal will list all the 100 and odd jpg files I have in the parent directory. But, copying them is simply not working.

@catkin:There were no error messages.

One more thing. Suppose I have a folder called 'night' and it contains 5 jpg files. When I try to run the same command on this directory, it will find and then copy all the jpg files to the destination directory. But, when I do the operation on the parent directory, as I said earlier, it is not even copying the files inside 'night' to the destination directory.
 
Old 03-31-2012, 05:40 AM   #7
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
Run the command without the -exec part and see what find finds. One possibility is that the filenames contain "evil" characters, so the cp command fails.

Often -print0 is used in the find command, and the results are piped to xargs with the -0 option. This uses NULL to separate the filenames.

Code:
find /source/directory -iname "*.jpg" -o -iname "*.png" -print0 | xargs -0 cp -t /target/directory
Also look at xargs options to limit the number of arguments handled at one time. A command like "cp /source/*.jpg /target/dir/" could fail when the shell expands the * wildcard. You can run out of memory.

Another use of xargs is to add arguments from a file.
Code:
tr '\n' '\0' <filelist | xargs -0 -L 500 cp -t /target/dir
 
Old 03-31-2012, 05:42 AM   #8
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by kbp View Post
I did the same as you catkin but it actually needs parentheses
Thanks kbp but I tested and it seemed OK without:
Code:
c@CW8:~/d$ find . -iname *.jpg -o -iname *.png 2>/dev/null | grep --count '.png' 
1532
c@CW8:~/d$ find . -iname *.jpg -o -iname *.png 2>/dev/null | grep --count '.jpg' 
6903
c@CW8:~/d$ find --version
find (GNU findutils) 4.4.2
[snip]
Different versions of find?
 
Old 03-31-2012, 05:46 AM   #9
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
Quote:
Originally Posted by matrix13 View Post
Thank you all for the explanations.

@catkin:There were no error messages.

One more thing. Suppose I have a folder called 'night' and it contains 5 jpg files. When I try to run the same command on this directory, it will find and then copy all the jpg files to the destination directory. But, when I do the operation on the parent directory, as I said earlier, it is not even copying the files inside 'night' to the destination directory.
This sounds like you still are not quoting the arguments to -iname. You also need single quotes around '{}' to handle files with spaces.

Code:
find sourcedir/ -iname "*.jpg" -o -iname "*.png" -exec cp '{}' target/dir/ \;
Another way of handling filenames with evil characters is to feed the filelist to xargs, using the -print0 option to separate each name with a NULL.

Code:
find sourcedir/ -iname "*.jpg" -o "*.png" -print0 | xargs -0 cp -t target/dir/
Note the parenthesis. You need them.

Last edited by jschiwal; 03-31-2012 at 05:48 AM.
 
Old 03-31-2012, 06:05 AM   #10
matrix13
Member
 
Registered: Nov 2006
Location: Kerala, India
Distribution: Arch Linux
Posts: 134

Original Poster
Rep: Reputation: 25
I believe this has to do something with evil characters.
I did 'cd' to the parent directory and tried the following (as I did in my terminal)

Code:
find . -iname "*.jpg" -exec cp '{}' /home/matrix/Pictures/wall/ \;
Resulted in no error messages. But only 7 files copied.
For the record, I didn't use single quotes for {} previously.

Next one.
Code:
find . -iname "*.jpg" -print0 | xargs -0 cp ~/Pictures/wall/
Got this error message
Quote:
cp: target `./lightning/1920x1200.jpg' is not a directory
and nothing got copied.

I could not make out anything. 'lightning' is one directory inside the pwd.

@jschiwal: I did not understand this code segment
Quote:
tr '\n' '\0' <filelist | xargs -0 -L 500 cp -t /target/dir
 
Old 03-31-2012, 11:04 PM   #11
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,573

Rep: Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142Reputation: 2142
For something as simple as this, I usually just skip find and do it by hand:

Code:
cp *.jpg */*.jpg */*/*.jpg /destination/
It's usually much faster doing it this way than futzing with find and passing filenames with illegal characters through exec, etc. It's only feasible if you only have a few levels of subdirectories and a few different extensions to look for though.



Edit: and if you still want to track down the find problem, stick an "echo" in front of your cp in the -exec, eg:
Code:
find . -iname "*.jpg" -exec echo cp '{}' /home/matrix/Pictures/wall/ \;
This should print out exactly what it's trying to run in cp, which might shed some light on why the cp is failing.

Last edited by suicidaleggroll; 03-31-2012 at 11:13 PM.
 
Old 03-31-2012, 11:51 PM   #12
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by matrix13 View Post
For the record, I didn't use single quotes for {} previously.
You got different results with and without the single quotes around {} ?

That's intriguing. I would like to understand how/why that happens. AFAIK they would be stripped by bash before find is run. On that basis they should (!) not make any difference.

Does this command show the "evil" characters (with and without single quotes around {}):
Code:
find . -iname "*.jpg" -exec /bin/ls --quoting-style=c {} \;
 
Old 04-01-2012, 10:59 PM   #13
jschiwal
LQ Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682Reputation: 682
The "tr" commands translates between two character sets. "tr '\n' '\0' <filelist" takes its input from filelist and translates newlines to nulls. The results are printed to stdout, which is piped into xargs.
 
  


Reply

Tags
copy, find, terminal



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
find files with pattern, then copy those files to another directory ncsuapex Programming 4 08-13-2010 03:38 PM
How to Copy files from local directory to a particular directory using alias dynamics Linux - Newbie 7 09-11-2009 04:19 PM
cp of dd image failed, better to mount image and then copy? bmcws Linux - Newbie 5 06-23-2009 06:41 PM
Cannot find a common directory trnz$mr Linux - Newbie 4 02-18-2009 06:15 PM
How to copy files after search in array from this directory to another directory! phanvinhgiap Programming 4 01-04-2009 06:48 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 02:21 AM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration