help with 'find' command

Issues related to applications and software problems
Post Reply
lightman47
Posts: 709
Joined: 2014/05/21 20:16:00
Location: Central New York, USA

help with 'find' command

Post by lightman47 » 2018/07/13 17:23:47

OK, I am driving myself crazy trying to learn enough about 'find' to get done what I wish - I am so close 'I can taste it'!

I have a shared folder on my server containing many hundreds of family photos, mostly jpg's, but also littered with HUGE movies (.mov), and other large type files. I've promised a couple family members a disk of photos (jpgs). I created a directory on my Desktop called PicCD - the idea being I'd populate it with the hierarchically DATE named photo files (example: ./2018/07/04/{photo_file_name.jpg), then burn it to CDs or DVDs when I got the size appropriate to the medium. The file naming system started years ago by Shotwell and maintained ever since.

Having hopefully give you sufficient info, I've researched and constructed a find command that is pretty much what I (in this initial stage) am looking for, but there's a glitch prompting this question:

Is there a bash regex to strip out the "./" from the second expansion of "{}" that I can include in my command - I am trying to recreate the tree' destination as many pics have the same name:

Code: Select all

find -iname "*.jpg" -exec cp {} $HOME/Desktop/PicCD/{} \;
which results (for every file attempt) in:
cp: cannot create regular file ‘/home/User/Desktop/PicCD/./1986/DuckGoosingGoose.jpg’: No such file or directory
I have more 'lesser puzzles' on which to wok after this is solved, but that doggone "PicCD/./1986 ..." is clobbering me. Then there's there's the photos getting re-dated to the date in which I perform my copy; but that's another day.

Thank you.
"Please solve your problems in advance so we can help you more"
- unknown

User avatar
TrevorH
Forum Moderator
Posts: 23482
Joined: 2009/09/24 10:40:56
Location: Brighton, UK

Re: help with 'find' command

Post by TrevorH » 2018/07/13 17:55:56

I believe the /./ is unimportant and ignored. I suspect the real problem is that you don't have a 1986 subdirectory under your PicCD directory.
CentOS 5 died in March 2017 - migrate NOW!
Full time Geek, part time moderator. Use the FAQ Luke

lightman47
Posts: 709
Joined: 2014/05/21 20:16:00
Location: Central New York, USA

Re: help with 'find' command

Post by lightman47 » 2018/07/13 18:46:43

Agreed - It doesn't exist; the goal is to create it (and it's subs as necessary).

In my example i used "cp", but I had previously also tried with 'rsync' and various switches. All baulk at that reference to a 'current directory' passed by find in the second "{} - and I don't blame them. My question is can I somehow "s/\.\///" the second parameter to delete the offensive reference?

Thank you.
"Please solve your problems in advance so we can help you more"
- unknown

User avatar
TrevorH
Forum Moderator
Posts: 23482
Joined: 2009/09/24 10:40:56
Location: Brighton, UK

Re: help with 'find' command

Post by TrevorH » 2018/07/13 19:08:38

It's NOT the /./ bit that's the problem. Every directory has a . and a .. entry in it. The .. one means the parent directory, the . entry means the current one. You can test this by running e.g. ls -la /home/Desktop/PicCD/./ and also ls -la /home/Desktop/PicdCD/ and the output from those two should be identical. In fact you can run ls -la /home/Desktop/PicCD/././././././ and you will still get the same output as it's the same path.
CentOS 5 died in March 2017 - migrate NOW!
Full time Geek, part time moderator. Use the FAQ Luke

lightman47
Posts: 709
Joined: 2014/05/21 20:16:00
Location: Central New York, USA

Re: help with 'find' command

Post by lightman47 » 2018/07/14 11:21:47

Hmm - now I am stumped. I'll probably play with this some more later today; perhaps it's a permission problem of some sort. I'll try creating the directory manually to see what happens.

EDIT1:
OK - I am 'suspicioning' that I may have to use rsync to do the file copying because I am trying to create multiple directory levels at once. As I recall, 'cp' doesn't like that! - I see more playing ahead ...
"Please solve your problems in advance so we can help you more"
- unknown

pjsr2
Posts: 342
Joined: 2014/03/27 20:11:07

Re: help with 'find' command

Post by pjsr2 » 2018/07/15 09:23:59

find -iname "*.jpg" -exec cp {} $HOME/Desktop/PicCD/{} \;
You should not use "*.jpg" as the pattern you want to use. As this is a double-quoted argument, the asterisk may get expanded by the shell when a file with a name that matches *.jpg, exists in the current directory. Use \*.jpg or '*.jpg' to prevent this kind of surprises from happening.

The cp command does not create any intermediate directory in your target directory. So cp is going to fail.

You can use the following approach:
- use "find" to create a list of files matching your pattern.
- create a tar-archive using the list created in the previous step
- extract the tar archive in your target directory.

You end up with something like:

Code: Select all

find -iname \*.jpg > /tmp/jpg-files
tar  --files-from=/tmp/jpg-file -c -f - | tar -C $HOME/Desktop/PicCD -x -f -
rm /tmp/jpg-files

User avatar
TrevorH
Forum Moderator
Posts: 23482
Joined: 2009/09/24 10:40:56
Location: Brighton, UK

Re: help with 'find' command

Post by TrevorH » 2018/07/15 10:37:56

As this is a double-quoted argument, the asterisk may get expanded by the shell when a file with a name that matches *.jpg, exists in the current directory
Double quotes work just fine for this purpose. I think you're thinking about variable substitution so your comment would be applicable if you were looking for files with $ signs in their names like `ls -la "$USER.jpg"` would substitute the value of $USER into the filename inside double quotes but will not inside single quotes and will find a file called exactly $USER.jpg".
CentOS 5 died in March 2017 - migrate NOW!
Full time Geek, part time moderator. Use the FAQ Luke

lightman47
Posts: 709
Joined: 2014/05/21 20:16:00
Location: Central New York, USA

Re: help with 'find' command

Post by lightman47 » 2018/07/16 17:30:26

OK - my problem appears to be the creation of the directories/sub-directories on the target drive. I can 'find' the files, and "{}" contains the filespec as it should, including the relative path to the file(s). But there's no "one-liner" command that will create directories with sub levels and then files apparently.

It appears I'll be either doing the work manually, or spend a great deal of time trying to write a script(s) to do it - reminiscent of my DOS 3 program in 8088 assembler that MOVEd files to as yet non-existent directories . I don't wish to work all that logic out again, but ...

:o
"Please solve your problems in advance so we can help you more"
- unknown

pjsr2
Posts: 342
Joined: 2014/03/27 20:11:07

Re: help with 'find' command

Post by pjsr2 » 2018/07/16 20:17:15

But there's no "one-liner" command that will create directories with sub levels and then files apparently.
The one-liner you need is not on http://www.bashoneliners.com/ :( .

Since you prefer a one-liner that contains the find command:

The find option -exec passes all the arguments following it into an exec call, and therefor you can only use a single command, not multiple commands connected through a pipe. You can work around by passing the script as an argument to the command sh. That gives the following solution:

Code: Select all

find -iname \*.jpg -exec sh -c "tar -c -f - {} | tar -C $HOME/Desktop/PicCD -x -f -" \; 
The disadvantage of the above solution is that it is rather inefficient as you are starting two tar processes for each file.

A more efficient solution in this situation is to let the find command create an argument list to the tar command with the help of xargs:

Code: Select all

find -iname \*.jpg -print0 | xargs --null tar -c -f - | tar -C $HOME/Desktop/PicCD -x -f -
Disadvantage of this solution is that it may fail in case the number of files found is very large.


Perfect is an enemy of good.

Post Reply