• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

cp select files recursively?

just had this on a test and couldnt seem to figure it out

the goal is to selectively go through a directory "dir1/" and its subdirectories and copy all files starting in a,e,i,o,u and ending in ".py" to dir2/

is there a way to do that with cp? googling around gave a couple of suggestions that didnt seem to work either (one using grep, another using xargs)

any ideas? cant go back and change anything but im curious

thank
 
use `find` with the -regex option coupled with the -exec option

ie:
find /path/dir1 -type f -regex 'regexpattern' -exec cp {} /path/dir2 \;

the regex pattern is the hard part.
use -iregex if you want it to be case insensitive
 
Here're a set of commands that worked for me

I had files <a,e,i,o,u>test.py, mixed in with others, in various nested subdirs

Code:
mkdir /dir2/
cd /dir1/
find . -type d -exec mkdir -p /dir2/{} \;
find . -type f -regex '.+/[aeiou].*\.py' -exec cp {} /dir2/{} \;

edits: had to adjust regex to filter unwanted patterns (ta.py, ablahpy, etc...)
 
Last edited:
yeah, thats all way more involved than anything im used to doing (im familiar with linux to a degree, but never got into playing with regex or xargs or anything similar)

thanks for the replies 🙂
 
yeah, thats all way more involved than anything im used to doing (im familiar with linux to a degree, but never got into playing with regex or xargs or anything similar)

thanks for the replies 🙂

I like this regex tutorial. Regex syntax makes things look cryptic and complicated, but it's really not (and incredibly useful) once you understand how it works.
 
Code:
mkdir /dir2/
cd /dir1/
find . -type d -exec mkdir -p /dir2/{} \;
>-exec cp {} /dir2/{} \;
edits: had to adjust regex to filter unwanted patterns (ta.py, ablahpy, etc...)

Fails if a directory is named alpha.py, then it returns everything listed under that directory.
 
Fails if a directory is named alpha.py, then it returns everything listed under that directory.

:hmm: Not everything, but yes, it does match stuff it shouldn't.

sample directory/file structure [ (#) where it should match]:
Code:
/test/temp1/
	./alpha.py/
		./a.py (1)
		./apy
		./atest.py (2)
		./atestpy
		./etest.py (3)
		./etest.txt
	./temp/
		./alpha.py/
			./o.py (4)
			./o.py.txt
			./otesteapy.py (5)
			./otesteapy.txt
			./test.py
		./alphapy/
			./otesteapy.py (6)
			./otesteapy.txt
			./test.py
		./otets.py (7)
		./totest.pypy
	./atest.py (8)
	./ta.py
	./test.txt
	./testa.py

From within temp1, output of find . -type f -regex '.+/[aeiou].*\.py':
(#) with valid match, ** with invalid match
Code:
find . -type f -regex '.+/[aeiou].*\.py'
./atest.py (8)
./alpha.py/atest.py (2)
./alpha.py/etest.py (3)
./alpha.py/a.py (1)
./temp/alphapy/otesteapy.py (6)
./temp/alphapy/test.py **
./temp/alpha.py/otesteapy.py (5)
./temp/alpha.py/o.py (4)
./temp/alpha.py/test.py **
./temp/otets.py (7)

Good exercise. Maybe someone better versed with regex can explain how to filter for such an issue.

OP could also just use multiple -name parameters instead, like the following, which gives a properly matched set:
Code:
> find . -type f /( -name 'a*.py' -o -name 'e*.py' -o -name 'i*.py' -o -name 'o*.py' -o -name 'u*.py' -o /)

./atest.py (8)
./alpha.py/atest.py (2)
./alpha.py/etest.py (3)
./alpha.py/a.py (1)
./temp/alphapy/otesteapy.py (6)
./temp/alpha.py/otesteapy.py (5)
./temp/alpha.py/o.py (4)
./temp/otets.py (7)
 
Last edited:
gooberlx2 I will tinker with it at work a bit on Tuesday and let you know.

I know that past the first / you will need to negate that / with [^/]... find from GNU Findutils by default uses emacs regex so it throws me off as I'm used to perl regex or awk's regex. (Its regex engine can be selected with a runtime option though)
 
So I've screwed with it some and the negation didn't work the way I thought it would... If you say [^/] all you're saying is "any character that is not /" ... so you'd have to do a negative lookahead, or a lookbehind assertion.

I'm going to go through the GNU findutils regex engines and see which ones do negative lookahead/lookbehind assertions. There may already be an answer on the interwebs!
 
Back
Top