Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BASH - find specific folder with find and filter with regex

Tags:

regex

bash

I have a folder containing many folders with subfolder (/...) with the following structre:

_30_photos/combined
_30_photos/singles
_47_foo.bar
_47_foo.bar/combined
_47_foo.bar/singles
_50_foobar

With the command find . -type d -print | grep '_[0-9]*_' all folder with the structure ** will be shown. But I have generate a regex which captures only the */combined folders: _[0-9]*_[a-z.]+/combined but when I insert that to the find command, nothing will be printed.

The next step would be to create for each combined folder (somewhere on my hdd) a folder and copy the content of the combined folder to the new folder. The new folder name should be the same as the parent name of the subfolder e.g. _47_foo.bar. Could that be achieved with an xargs command after the search?

like image 754
mybecks Avatar asked Aug 22 '12 13:08

mybecks


3 Answers

You do not need grep:

find . -type d -regex ".*_[0-9]*_.*/combined"

For the rest:

find . -type d -regex "^\./.*_[0-9]*_.*/combined" | \
   sed 's!\./\(.*\)/combined$!& /somewhere/\1!'   | \
   xargs -n2 cp -r
like image 178
perreal Avatar answered Nov 19 '22 06:11

perreal


With basic grep you will need to escape the +:

... | grep '_[0-9]*_[a-z.]\+/combined'

Or you can use the "extended regexp" version (egrep or grep -E [thanks chepner]) in which the + does not have to be escaped.

xargs may not be the most flexible way of doing the copying you describe above, as it is tricky to use with multiple commands. You may find more flexibility with a while loop:

... | grep '_[0-9]*_[a-z.]\+/combined' | while read combined_dir; do 
    mkdir some_new_dir
    cp -r ${combined_dir} some_new_dir/
done

Have a look at bash string manipulation if you want a way to automate the name of some_new_dir.

like image 37
Lee Netherton Avatar answered Nov 19 '22 05:11

Lee Netherton


target_dir="your target dir"

find . -type d -regex ".*_[0-9]+_.*/combined" | \
  (while read s; do
     n=$(dirname "$s")
     cp -pr "$s" "$target_dir/${n#./}"
   done
  )

NOTE:

  • this fails if you have linebreaks "\n" in your directory names
  • this uses a subshell to not clutter your env - inside a script you don't need that
  • changed the regex slightly: [0-9]* to [0-9]+
like image 1
tzelleke Avatar answered Nov 19 '22 06:11

tzelleke