LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   cp propblem in BASH (https://www.linuxquestions.org/questions/linux-software-2/cp-propblem-in-bash-4175439606/)

Calgarian 12-01-2012 12:56 PM

cp propblem in BASH
 
I am trying to write a script to move all occurences of a file type from a directory structure including all sub-directories, into a single directory. For example: from a structure music/different artists/different album names/different songs.mp3 collect all the mp3 files into a directory /songs. The names contain spaces, except for the destination directory, and I'm not concerned about duplicate names in the source.

I have all the basics of getting the base directory name, file type, and source directory name settled in the script. I'm trying the following find/cp command which I think should walk down from the base directory. I get the target directory created, but no files are copied into it and no error messages created. Here is my find/cp command. What silly mistake have I made? I'm suspicious that i"ve messed up the quotes or double quotes - or I really don't understand how the {} works in the cp command.


find "$BASE_DIR" -type f -name '*.$FILE_TYPE' -exec cp '{}' $NEW_DIR/'{}' \;

H_TeXMeX_H 12-01-2012 01:22 PM

This should work:

Code:

find /source -iname '*.mp3' -print0 | xargs -0 mv -t /destination
Replace source and destination directories.

If you didn't want to clobber files you would add '-n' to the mv arguments. Note that '-iname' means ignore case, if you don't want to ignore case use '-name' instead, but you usually want to ignore case. I mean the extension can be '.MP3' instead of '.mp3'.

Calgarian 12-01-2012 01:32 PM

I am actually trying to just copy them, not move them. I want to use the resulting directory for some other work without touching the originals. Also, I can't seem to find out what the -t option actually does?

Calgarian 12-01-2012 02:30 PM

A little more digging and reading and moving the target directory out of the base directory and I got it to work.

find "$BASE_DIR" -type f -name *.$FILE_TYPE -exec cp {} $NEW_DIR \;

H_TeXMeX_H 12-02-2012 02:35 AM

Just replace 'mv' with 'cp'. Read the man pages and you will see that '-t' means destination directory.

Code:

find /source -iname '*.mp3' -print0 | xargs -0 cp -t /destination
Make sure to use single quotes around the '*' for the iname parameter or bash may expand that before find can use it.

David the H. 12-02-2012 02:35 PM

Please use ***[code][/code]*** tags around your code and data, to preserve the original formatting and to improve readability. Do not use quote tags, bolding, colors, "start/end" lines, or other creative techniques.

Your find command can be made more efficient this way:

Code:

find "$BASE_DIR" -type f -name "*.$FILE_TYPE" -exec cp -t "$NEW_DIR" '{}' \+
Changing ";" to "+" at the end of the -exec option makes it operate in batch mode, similar to how xargs works. But this requires the use of the -t option in cp and mv; since the '{}' substitution now represents all of the files found and can only appear at the end of the command.

Notice also how I quoted all the variables, and, as Tex-Mex mentioned, especially the -name argument. Otherwise the shell will attempt to expand globbing characters like the '*' and word-split all expanded strings before executing the command itself.

Proper quoting is a vitally important concept in shell scripting, so train yourself to do it correctly now.

http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes


All times are GMT -5. The time now is 08:36 AM.