I have multiple directories named such as:

and so on...

each contains 7 files having an extension of .raw. Examples of the files in one of the directories would be:

...until n7.raw

I want the script to go to each directory and copy the .raw files to a new directory outside of their parent directory so that I can have all the .raw files at the same place at the end of the whole exercise.

Any help would be much appreciated.

  • Your question is a little vague.  You say "I have ... directories named ..." Are these all subdirectories of one large, parent directory? Are there other subdirectories, with names not matching that scheme, that you need to ignore?  You say "I want .... copy the .raw files to a new directory ..." Do you mean one huge, new directory? Or one for each of the .frames directories?  And, BTW, note that n0, n1, n2, ..., n7 adds up to eight files. – G-Man Says 'Reinstate Monica' Mar 30 '15 at 10:19

Assuming the *frames directories are all in the same directory, you can do something like

cd to/the/parent/of/the/frames/dirs
mkdir all-my-raws
cp *.frames/*.raw all-my-raws/

To avoid duplication of files you can replace cp with ln to just create a new link to the same data.

| improve this answer | |

You can use find for this.

find /path/to/directories -type f -name "*.raw" -exec cp {} /new/path \;

If you want to move the files instead of copying them, replace cp with mv After moving the files you can remove empty directories with find /path/to/directories -type d -empty -exec rmdir {} \;

| improve this answer | |
  • or link the files with ln or cp -l ... – Skaperen Mar 30 '15 at 10:06

My proposed solution:

  1. Collect list of all directories in a bash array. Something like dirs=($(ls *.frames)) This way you will have all the directory names in an array.

  2. Run a loop for the entire range with something like for i in ${$dirs[@]}; do......

  3. Within the loop, create a new directory somewhere, & move all files from current directory to that location. Something like

    for i in ${$dirs[@]}; do
        mkdir dir_$i
        mv ($i)/*.raw dir_$i/

This might need some minor tweaking, but pretty sure this will work.

P.S. - Try something better to create the new directories :P

| improve this answer | |
  • This complication only if you wanted all the raw files to be in different locations. If not, Patrix's solution is simpler. I use a similar script to clean all my git repo directories. – Stark07 Mar 30 '15 at 10:02
  • 1
    You didn’t try this yourself, did you?  Parsing the output of ls (i.e., using it for subsequent command processing, rather than just displaying it) is never a good idea.  But your dirs=($(ls *.frames)) suggestion is outright wrong.  Think about what you get if you type ls *.frames — you get a listing of the contents of the *.frames directories.  … (Cont’d) – G-Man Says 'Reinstate Monica' Mar 30 '15 at 10:54
  • 1
    (Cont’d) …  So that’s what you get in your dirs variable when you use the dirs=($(ls *.frames)) command.  You can fix that problem by saying dirs=($(ls -d *.frames)) — but that breaks if any of the *.frames directories has a space in its name.  The ‘right’ way to do this is simply dirs=(*.frames) — but even that will include any files whose names match the *.frames pattern. – G-Man Says 'Reinstate Monica' Mar 30 '15 at 10:56
  • Ouch. I did say you would need some tweaking... I don't use this script to move files. And in case of dirs=(*.frames), we can have a simple check to see of it's a directory. file $i | grep directory, if [ $? -eq 0 ] then ...... fi – Stark07 Mar 30 '15 at 11:06
  • 1
    … Or simply if [ -d "$i" ]; then ….  By the way, it's a really good idea to quote all your shell variables unless you have a good reason not to and you're sure you know what you're doing. – G-Man Says 'Reinstate Monica' Mar 30 '15 at 11:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.