Tôi thường sử dụng find
lệnh để tìm kiếm thông qua mã nguồn, xóa các tập tin, bất cứ điều gì. Khó chịu, vì Subversion lưu trữ các bản sao của mỗi tệp trong .svn/text-base/
thư mục của nó, các tìm kiếm đơn giản của tôi cuối cùng nhận được rất nhiều kết quả trùng lặp. Ví dụ: tôi muốn tìm kiếm đệ quy uint
trong nhiều tệp messages.h
và messages.cpp
tệp:
# find -name 'messages.*' -exec grep -Iw uint {} +
./messages.cpp: Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./messages.cpp: Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./messages.cpp: Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./messages.cpp: Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./messages.cpp: Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./messages.cpp: Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./messages.cpp: for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Discarding out of date message: id " << uint(olderMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Added to send queue: " << *message << ": id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: Log::error << "Received message with invalid SHA-1 hash: id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Received " << *message << ": id " << uint(incomingMessage.id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Sent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: Log::verbose << "Discarding unsent message: id " << uint(preparedMessage->id)
./.svn/text-base/messages.cpp.svn-base: for (uint i = 0; i < 10 && !_stopThreads; ++i) {
./virus/messages.cpp:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/messages.cpp:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/messages.h: void _progress(const std::string &fileName, uint scanCount);
./virus/messages.h: ProgressMessage(const std::string &fileName, uint scanCount);
./virus/messages.h: uint _scanCount;
./virus/.svn/text-base/messages.cpp.svn-base:void VsMessageProcessor::_progress(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.cpp.svn-base:ProgressMessage::ProgressMessage(const string &fileName, uint scanCount)
./virus/.svn/text-base/messages.h.svn-base: void _progress(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base: ProgressMessage(const std::string &fileName, uint scanCount);
./virus/.svn/text-base/messages.h.svn-base: uint _scanCount;
Làm thế nào tôi có thể nói find
để bỏ qua các .svn
thư mục?
Cập nhật : Nếu bạn nâng cấp máy khách SVN lên phiên bản 1.7 thì đây không còn là vấn đề nữa.
Một tính năng chính của các thay đổi được giới thiệu trong Subversion 1.7 là tập trung lưu trữ siêu dữ liệu sao chép hoạt động vào một vị trí. Thay vì một
.svn
thư mục trong mỗi thư mục trong bản sao làm việc, các bản sao làm việc của Subversion 1.7 chỉ có một.svn
thư mục trong thư mục gốc của bản sao làm việc. Thư mục này bao gồm (trong số những thứ khác) một cơ sở dữ liệu được hỗ trợ SQLite chứa tất cả các nhu cầu Subversion siêu dữ liệu cho bản sao làm việc đó.
-exec
với +
không phân nhánh grep
cho mỗi tập tin, trong khi sử dụng nó với ;
làm. Sử dụng -exec
thực sự đúng hơn sử dụng xargs
. Xin lưu ý rằng các lệnh như ls
làm một cái gì đó ngay cả khi danh sách đối số trống, trong khi các lệnh như chmod
đưa ra lỗi nếu không có đủ đối số. Để xem ý tôi là gì, chỉ cần thử lệnh sau trong thư mục không có bất kỳ tập lệnh shell nào : find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755
. So sánh với cái này : find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'
.
grep
ra ngoài .svn
cũng không phải là một ý kiến hay. Trong khi find
là chuyên ngành để xử lý các thuộc tính tập tin, grep
không. Trong ví dụ của bạn, một tệp có tên '.svn.txt' cũng sẽ được lọc theo egrep
lệnh của bạn . Mặc dù bạn có thể sửa đổi regex của mình thành '^ / \. Svn $' , nhưng vẫn không phải là một cách thực hành tốt. Vị -prune
từ find
hoạt động hoàn hảo để lọc tệp (theo tên tệp hoặc dấu thời gian tạo hoặc bất kỳ điều kiện nào bạn cung cấp). Nó cũng giống như ngay cả khi bạn có thể giết một con gián bằng một thanh kiếm lớn không có nghĩa đó là cách được đề xuất để làm như vậy :-).
find ... -print0 | xargs -0 egrep ...
thay vìfind ... -exec grep ...
(không rẽ nhánhgrep
cho mỗi tệp, nhưng cho một loạt các tệp cùng một lúc). Sử dụng biểu mẫu này, bạn cũng có thể cắt tỉa các.svn
thư mục mà không cần sử dụng-prune
tùy chọn tìm, tức làfind ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...