3

I am searching for some folders in my current directory. What I want to do is, move all the files within those directories to another directory. I am using the following command:

find -maxdepth 1 -regex 'myRegexExpHere' | xargs -I file mv file/* Desktop/New\ folder/

But as expected, the '*' is not expanded by xargs, instead searching for a file named * in each folder. What should I do to achieve my aim? Please suggest ways involving the use of xargs only (and not the -exec switch of find), primarily because I have read that using xargs is much more efficient.

2
  • find -exec … + is even more efficient than xargs. And further, it probably doesn't matter—the moves themnselves will most likely be the vast majority of the time.
    – derobert
    Nov 12, 2013 at 22:44
  • Yeah, I guess I will have to resort to -exec if I don't get any other solution. Besides, as you said, the move part is the major time-hogger, so it probably doesn't matter.
    – Parag Goel
    Nov 13, 2013 at 6:41

2 Answers 2

3

You need the expansion of the wildcard to happen in a shell that's executed after file has been replaced by the name of the matching file. So you need to start a shell from xargs.

Better than using xargs, use the exec predicate to find. It's simpler and doesn't suffer from quoting issues.

find -maxdepth 1 -regex 'myRegexExpHere' -exec sh -c 'mv "$0"/* Desktop/New\ folder/' {} \;

You're probably overcomplicating things. This simple use of find can be expressed directly in most shells. Ksh has a syntax for regular expressions:

  • @(EXPR1|EXPR2) matches EXPR1 or EXPR2
  • *(EXPR) matches 0 or more occurrence of EXPR
  • +(EXPR) matches 1 or more occurrence of EXPR
  • ?(EXPR) matches 0 or 1 occurrence of EXPR

This syntax is also available in bash if you run shopt -s extglob first, and in zsh if you run setopt ksh_glob first. Then you can use

mv REGEX/* Desktop/New\ folder/
1

Why use find when you don't need recursion? Use the shell (I'm assuming Bash here, modify to suit your needs) for regex matching:

for dir in */;do
    if [[ "$dir" =~ yourRegexHere ]];then
        mv -- "$dir"/* "Desktop/New folder/"
    fi
done

If your shell's regex capabilities are too weak for your requirements, it doesn't get any better than Perl:

perl -e 'for(grep {/yourRegexHere/} glob "*/"){ 
             qx(mv -- "$_"/* "Desktop/New folder") 
         }'
1
  • So I should always try to use a loop when I need to perform such operations? What are the cases then where a single command would benefit me?
    – Parag Goel
    Nov 13, 2013 at 6:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .