9

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?

AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173
mybecks
  • 2,443
  • 8
  • 31
  • 43
  • 1
    if you insert your regex into -regex option with find be aware that find matches the full path -> if you start from . then the regex MUST match ./whatever/come.here – tzelleke Aug 22 '12 at 13:35
  • 1
    This sounds suspiciously like an [XY Problem](http://mywiki.wooledge.org/XyProblem). mybecks, what are you *really* trying to achieve? – ghoti Aug 22 '12 at 14:07
  • is it possible to tell find that it should search only inside this (or predefined) directory and of course in all subdirs – mybecks Aug 22 '12 at 14:08
  • @mybecks ...but isn't that what you tell find with the very first argument – tzelleke Aug 22 '12 at 14:48
  • I had think that to, but realized that all folder with that naming are found (and deleted, I use that find command for deleting too) – mybecks Aug 24 '12 at 10:34

4 Answers4

11

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
perreal
  • 94,503
  • 21
  • 155
  • 181
4

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.

Community
  • 1
  • 1
Lee Netherton
  • 21,347
  • 12
  • 68
  • 102
  • if I do `echo $combined_dir` it prints out the whole path ./_00_foo.bar/combined. THis is okay. But now I want to copy the content of /combined to the main dir (_00_foo.bar). Therefore I used the following syntax inside the loop:`CURRENT_DIR=$(echo $combined_dir | grep "_[0-9]*_[a-z.]\+")` but I doesn't work :( – mybecks Aug 27 '12 at 07:00
1
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]+
tzelleke
  • 15,023
  • 5
  • 33
  • 49
0

You can use this command:

find . -type d | grep -P "_[0-9]*_[a-z.]+/combined"