문제

UNIX bash 쉘 (특히 Mac OS X Leopard)에서 특정 확장자를 가진 모든 파일을 폴더 계층 (하위 디렉토리 포함)에서 동일한 대상 폴더 (하위 폴더없이)로 복사하는 가장 간단한 방법은 무엇입니까?

분명히 소스 계층 구조에 중복 항목이있는 문제가 있습니다.덮어 써도 괜찮습니다.

예 : 다음 계층 구조의 모든 .txt 파일을 복사해야합니다. 라코 디스

'dest'라는 폴더로 이동하여 다음을 가져옵니다. 라코 디스

도움이 되었습니까?

해결책

bash에서 : 라코 디스

find는 대소 문자를 구분하지 않고 와일드 카드 /foo와 일치하는 *.txt 경로 아래의 모든 파일을 찾습니다 (즉, -iname가 의미하는 바입니다).각 파일에 대해 findcp {} /dest/ 대신 발견 된 파일을 사용하여 {}를 실행합니다.

다른 팁

The only problem with Magnus' solution is that it forks off a new "cp" process for every file, which is not terribly efficient especially if there is a large number of files.

On Linux (or other systems with GNU coreutils) you can do:

find . -name "*.xml" -print0 | xargs -0 echo cp -t a

(The -0 allows it to work when your filenames have weird characters -- like spaces -- in them.)

Unfortunately I think Macs come with BSD-style tools. Anyone know a "standard" equivalent to the "-t" switch?

The answers above don't allow for name collisions as the asker didn't mind files being over-written.

I do mind files being over-written so came up with a different approach. Replacing each / in the path with - keep the hierarchy in the names, and puts all the files in one flat folder.

We use find to get the list of all files, then awk to create a mv command with the original filename and the modified filename then pass those to bash to be executed.

find ./from -type f | awk '{ str=$0; sub(/\.\//, "", str); gsub(/\//, "-", str); print "mv " $0 " ./to/" str }' | bash

where ./from and ./to are directories to mv from and to.

If you really want to run just one command, why not cons one up and run it? Like so:

$ find /foo  -name '*.txt' | xargs echo | sed -e 's/^/cp /' -e 's|$| /dest|' | bash -sx

But that won't matter too much performance-wise unless you do this a lot or have a ton of files. Be careful of name collusions, however. I noticed in testing that GNU cp at least warns of collisions:

cp: will not overwrite just-created `/dest/tubguide.tex' with `./texmf/tex/plain/tugboat/tubguide.tex'

I think the cleanest is:

$ find /foo  -name '*.txt' | xargs -i cp {} /dest

Less syntax to remember than the -exec option.

As far as the man page for cp on a FreeBSD box goes, there's no need for a -t switch. cp will assume the last argument on the command line to be the target directory if more than two names are passed.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top