Làm cách nào tôi có thể nhận được `find` để bỏ qua các thư mục .svn?


227

Tôi thường sử dụng findlệ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 uinttrong nhiều tệp messages.hmessages.cpptệ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 .svnthư 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 .svnthư 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 .svnthư 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 đó.


4
Để thực hiện, hãy thử sử dụng find ... -print0 | xargs -0 egrep ...thay vì find ... -exec grep ...(không rẽ nhánh grepcho 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 .svnthư mục mà không cần sử dụng -prunetùy chọn tìm, tức làfind ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...
vladr

3
@Vlad: Theo như tôi biết, sử dụng -execvới +không phân nhánh grepcho mỗi tập tin, trong khi sử dụng nó với ;làm. Sử dụng -execthực sự đúng hơn sử dụng xargs. Xin lưu ý rằng các lệnh như lslà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 '{}' '+'.
Siu Ching Pong -Asuka Kenji-

2
@Vlad: Bên cạnh đó, grepra ngoài .svncũng không phải là một ý kiến ​​hay. Trong khi findlà chuyên ngành để xử lý các thuộc tính tập tin, grepkhông. Trong ví dụ của bạn, một tệp có tên '.svn.txt' cũng sẽ được lọc theo egreplệ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ị -prunetừ findhoạ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 :-).
Siu Ching Pong -Asuka Kenji-

3
Chuyển sang Git đã khắc phục sự cố này (trong số nhiều người khác). Trong chỉ tạo một thư mục .git trên thư mục gốc của bản sao hoạt động, không phải trong mọi thư mục của nó như SVN. Ngoài ra, thư mục .git không chứa các tệp đơn giản sẽ bị nhầm lẫn với các tệp thực tế của bạn có cùng tên.
Tronic

3
2Dan Moulding: svn 1.7 chỉ tạo một thư mục .svn cấp cao nhất
ccpizza

Câu trả lời:


65

Để tìm kiếm, tôi có thể đề nghị bạn nhìn vào ack ? Đó là nhận thức về mã nguồn findvà như vậy sẽ tự động bỏ qua nhiều loại tệp, bao gồm thông tin kho lưu trữ mã nguồn như ở trên.


3
Tôi ackrất thích , nhưng tôi đã thấy nó chậm hơn đáng kể so với find -type f -name "*.[ch]" | xargs grepkhi giao dịch với một cơ sở mã lớn.
John Ledbetter

63
John, tôi là tác giả của ack và nếu bạn có thể cho tôi biết chi tiết về các vấn đề tốc độ của ack so với grep, tôi sẽ đánh giá cao nó. Chúng hoàn toàn có thể so sánh trong tất cả các trường hợp tôi tìm thấy. Hoặc cho tôi biết tại github.com/petdance/ack/issues hoặc gửi email cho tôi tại andy tại petdance.com. Tiếng Phạn.
Andy Lester

63
Các bạn, đó là một mẹo, nhưng chắc chắn không phải là một câu trả lời cho câu hỏi! :)
dolzenko

8
Không được acklập hóa đơn là tốt hơn grep, không phải là nhận thức nguồn find? Một số ví dụ về việc sử dụng nó để thay thế findsẽ làm cho điều này trở thành một câu trả lời thực sự.
michiakig

3
Đó là một câu trả lời cho câu hỏi mà anh không biết mình đang hỏi. =)
Frungi

293

tại sao không chỉ

find . -not -iwholename '*.svn*'

Vị từ -not phủ nhận mọi thứ có .svn ở bất cứ đâu trong đường dẫn.

Vì vậy, trong trường hợp của bạn, nó sẽ là

find -not -iwholename '*.svn*' -name 'messages.*' -exec grep -Iw uint {} + \;

5
+1 siêu lớn cho "-không" và "-iwholename". Ack là tuyệt vời và tôi sử dụng nó, nhưng find / exec vẫn có công dụng của nó.
David Blevins

9
Câu trả lời duy nhất thực sự trả lời câu hỏi ban đầu.
Brendon Crawford

14
Tôi thoát khỏi yếu tố của mình và tôi chắc chắn rằng tôi sẽ bị chỉ trích vì nhận xét này, nhưng rõ ràng -not và -wholename không tuân thủ POSIX. Tôi đã sử dụng! thay cho -not và -path thay cho -iwholename và nhận được kết quả tương tự. Theo trang người đàn ông của tôi (Ubuntu 12.04) cú pháp này tuân thủ POSIX.
Giăng

1
@whaley Lúc đầu bạn nói '*.svn*'nhưng sau đó '*.svn'. Cái nào đúng? Làm cả hai? Tôi nghĩ có lẽ nên như '*.svn*'vậy?
Keith M

1
@KeithM bắt tuyệt vời thực sự. Câu trả lời này đã được ngồi ở đây trong nhiều năm và tôi không nghĩ có ai đã bắt được điều đó cho đến bây giờ.
cá voi

141

Như sau:

find . -path '*/.svn*' -prune -o -print

Hoặc, thay vào đó dựa trên một thư mục chứ không phải tiền tố đường dẫn:

find . -name .svn -a -type d -prune -o -print

14
@Kaleb: Xin chào. Tôi đề nghị find . -type d -name .svn -prune -o -printvì nó nhanh hơn một chút. Theo tiêu chuẩn POSIX , các biểu thức được đánh giá từng cái một, theo thứ tự được chỉ định. Nếu biểu thức đầu tiên -afalse, biểu thức thứ hai sẽ không được đánh giá (còn được gọi là ngắn mạch và đánh giá ).
Siu Ching Pong -Asuka Kenji-

2
@Kaleb: Khi so sánh loại tệp (tương đương với việc kiểm tra xem một bit được đặt trong một số nguyên) có nhanh hơn so với so sánh tên tệp (tương đương với so sánh chuỗi, là O (n)), đặt -type dtrước -name .svnvề mặt lý thuyết sẽ hiệu quả hơn. Tuy nhiên, nó thường không đáng kể trừ khi bạn có một cây thư mục rất lớn.
Siu Ching Pong -Asuka Kenji-

5
@ SiuC BreathPong-AsukaKenji- không, chỉ so sánh tên tệp là nhanh hơn vì -type yêu cầu một lệnh gọi (2) trên mỗi tệp. Tuy nhiên, tên tệp là một phần của phản hồi readdir (3).
hraban

3
@JonathanHartley Bạn đang thiếu -printmột phần của biểu thức cuối cùng. Một cái gì đó như find . -name .git -prune -o \( -type f -name LICENSE -print \)hoạt động như mong đợi.
sschuberth

1
Nếu bạn muốn bỏ qua cả .git và .svn và chỉ liệt kê các thư mục khác , find . -name .svn -prune -o -name .git -prune -o -type d -print. Nó có thể nhanh hơn vài mili giây -type dtrước cả hai -name, nhưng nó không đáng để gõ thêm.
JPaget

34

Để bỏ qua .svn, .gitvà thư mục ẩn khác (bắt đầu với một dấu chấm), hãy thử:

find . -type f -not -path '*/\.*'

Tuy nhiên, nếu mục đích sử dụng findlà tìm kiếm trong các tệp, bạn có thể thử sử dụng các lệnh sau:

  • git grep - lệnh được thiết kế đặc biệt để tìm kiếm các mẫu trong kho Git.
  • ripgrep- mà theo mặc định bỏ qua các tập tin ẩn và tập tin được chỉ định trong .gitignore.

Liên quan: Làm cách nào để tìm tất cả các tệp chứa văn bản cụ thể trên Linux?


Câu trả lời hay nhất imo. Những người khác cố gắng giải thích những điều không trả lời câu hỏi đơn giản.
Anthony

19

Đây là những gì tôi sẽ làm trong trường hợp của bạn:

find . -path .svn -prune -o -name messages.* -exec grep -Iw uint {} +

rgrepLệnh tích hợp của Emacs bỏ qua .svnthư mục và nhiều tệp khác mà bạn có thể không quan tâm khi thực hiện a find | grep. Đây là những gì nó sử dụng theo mặc định:

find . \( -path \*/SCCS -o -path \*/RCS -o -path \*/CVS -o -path \*/MCVS \
          -o -path \*/.svn -o -path \*/.git -o -path \*/.hg -o -path \*/.bzr \
          -o -path \*/_MTN -o -path \*/_darcs -o -path \*/\{arch\} \) \
     -prune -o \
       \( -name .\#\* -o -name \*.o -o -name \*\~ -o -name \*.bin -o -name \*.lbin \
          -o -name \*.so -o -name \*.a -o -name \*.ln -o -name \*.blg \
          -o -name \*.bbl -o -name \*.elc -o -name \*.lof -o -name \*.glo \
          -o -name \*.idx -o -name \*.lot -o -name \*.fmt -o -name \*.tfm \
          -o -name \*.class -o -name \*.fas -o -name \*.lib -o -name \*.mem \
          -o -name \*.x86f -o -name \*.sparcf -o -name \*.fasl -o -name \*.ufsl \
          -o -name \*.fsl -o -name \*.dxl -o -name \*.pfsl -o -name \*.dfsl \
          -o -name \*.p64fsl -o -name \*.d64fsl -o -name \*.dx64fsl -o -name \*.lo \
          -o -name \*.la -o -name \*.gmo -o -name \*.mo -o -name \*.toc \
          -o -name \*.aux -o -name \*.cp -o -name \*.fn -o -name \*.ky \
          -o -name \*.pg -o -name \*.tp -o -name \*.vr -o -name \*.cps \
          -o -name \*.fns -o -name \*.kys -o -name \*.pgs -o -name \*.tps \
          -o -name \*.vrs -o -name \*.pyc -o -name \*.pyo \) \
     -prune -o \
     -type f \( -name pattern \) -print0 \
     | xargs -0 -e grep -i -nH -e regex

Nó bỏ qua các thư mục được tạo bởi hầu hết các hệ thống kiểm soát phiên bản, cũng như các tệp được tạo cho nhiều ngôn ngữ lập trình. Bạn có thể tạo một bí danh gọi lệnh này và thay thế findgrepcác mẫu cho các vấn đề cụ thể của bạn.


12

GNU tìm

find .  ! -regex ".*[/]\.svn[/]?.*"

Tôi đã tải các đường dẫn thư mục vào một mảng để PHP xử lý. Các câu trả lời khác cao hơn (vì bất kỳ lý do gì) đã không lọc ra các tệp trong tìm kiếm (mặc dù -type d) - câu trả lời này đã làm. +1
được hollenbeck

11

Tôi sử dụng grep cho mục đích này. Đặt cái này trong ~ / .bashrc của bạn

export GREP_OPTIONS="--binary-files=without-match --color=auto --devices=skip --exclude-dir=CVS --exclude-dir=.libs --exclude-dir=.deps --exclude-dir=.svn"

grep tự động sử dụng các tùy chọn này trên lệnh


1
Điều đáng chú ý là 'grep' chỉ đạt được tùy chọn '--exclude-dir' một hoặc hai năm trước. Các bản phân phối Linux gần đây bao gồm nó, nhưng nếu tôi nhớ chính xác, tôi đã phải biên dịch grep của riêng tôi (hoặc yêu cầu homebrew làm điều đó) trên OSX.
Jonathan Hartley

Tôi sử dụng một biến thể nhỏ của điều này. .Bashrc của tôi tạo ra hàm Bash 'grp', được định nghĩa là GREP_OPTIONS=xxx grep "$@". Điều này có nghĩa là biến GREP_OPTIONS chỉ được đặt cho các trường hợp grep mà tôi chạy thủ công bằng cách sử dụng 'grp'. Điều này có nghĩa là tôi không bao giờ gặp phải tình huống khi tôi chạy một công cụ và bên trong nó gọi là grep, nhưng công cụ bị lẫn lộn vì grep không hoạt động như mong đợi. Ngoài ra, tôi có một chức năng thứ hai là 'grpy', gọi là 'grp', nhưng thêm vào --include=*.py, chỉ để tìm kiếm các tệp Python.
Jonathan Hartley

Trên thực tế, về phản xạ, làm theo cách của tôi không còn cần phải sử dụng GREP_OPTIONS nữa. Bây giờ tôi chỉ có một hàm shell 'grp' mà gọi grep --exclude=tags --exclude_dir=.git ...etc... "$@". Tôi thích cái này chạy như 'ack', nhưng tôi giữ được nhận thức và kiểm soát những gì nó đang làm.
Jonathan Hartley

9

find . | grep -v \.svn


Bạn phải thoát .trong .svnregrec.
vladr

4
Sử dụng --fixed-string với grep: | fgrep -v /.svn/hoặc `| grep -F -v / .svn / `để loại trừ chính xác thư mục và không phải các tệp có" .svn "như một phần của tên của chúng.
Stephen P

8

Tại sao bạn không đặt lệnh của bạn với grep dễ hiểu:

your find command| grep -v '\.svn'

Bạn phải thoát .trong .svnregrec.
vladr

@Yclian không có bóng dáng của một nghi ngờ; nếu bạn không, các thư mục có tên 'tsvn', '1svn', 'asvn', v.v. cũng sẽ bị bỏ qua kể từ '.' là một ký tự đại diện regrec: 'khớp với bất kỳ ký tự nào'.
vladr

Được rồi, tôi nghĩ nó sẽ chỉ xảy ra với trường hợp -E và -G. Tôi chỉ thử nghiệm, xấu của tôi. :(
yclian

2
Tôi thích câu trả lời này vì nó đơn giản hơn về mặt khái niệm so với tất cả những câu hỏi khác. Tôi không thể nhớ cú pháp lố bịch cho việc sử dụng 'find', nhưng tôi chắc chắn có thể nhớ cách sử dụng grep -v vì nó được sử dụng trong rất nhiều tình huống.
mattismyname

8

Tạo một tập lệnh gọi là ~/bin/svnfind:

#!/bin/bash
#
# Attempts to behave identically to a plain `find' command while ignoring .svn/
# directories.

OPTIONS=()
PATHS=()
EXPR=()

while [[ $1 =~ ^-[HLP]+ ]]; do
    OPTIONS+=("$1")
    shift
done

while [[ $# -gt 0 ]] && ! [[ $1 =~ '^[-(),!]' ]]; do
    PATHS+=("$1")
    shift
done

# If user's expression contains no action then we'll add the normally-implied
# `-print'.
ACTION=-print

while [[ $# -gt 0 ]]; do
    case "$1" in
       -delete|-exec|-execdir|-fls|-fprint|-fprint0|-fprintf|-ok|-print|-okdir|-print0|-printf|-prune|-quit|-ls)
            ACTION=;;
    esac

    EXPR+=("$1")
    shift
done

if [[ ${#EXPR} -eq 0 ]]; then
    EXPR=(-true)
fi

exec -a "$(basename "$0")" find "${OPTIONS[@]}" "${PATHS[@]}" -name .svn -type d -prune -o '(' "${EXPR[@]}" ')' $ACTION

Kịch bản lệnh này hoạt động giống hệt một findlệnh đơn giản nhưng nó cắt bỏ các .svnthư mục. Nếu không thì hành vi là giống hệt nhau.

Thí dụ:

# svnfind -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) {
./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;

Kịch bản này không hoạt động như tôi mong đợi. Khi chạy nó với "svnfind -type f", nó cũng in các thư mục svn và các tệp trong thư mục svn
Ingo Fischer

@ifischer Bạn có thể thêm một echolệnh vào lệnh find và cho tôi biết lệnh nào được thực thi không? svnfind -type fhoạt động tuyệt vời trên máy Red Hat của tôi.
John Kugelman

Ok vì vậy nó có vẻ là phụ thuộc hệ điều hành. Tôi đang chạy Debian Squeeze (tương tự trên Ubuntu). Tôi không hiểu ý của bạn bằng cách "thêm tiếng vang"?
Ingo Fischer

@ifischer Thay đổi dòng cuối cùng để echo find "${OPTIONS[@]}"...nó in lệnh find thay vì thực sự chạy nó.
John Kugelman

Ok đã thay đổi dòng cuối cùng thành echo find ${OPTIONS[@]} ${PATHS[@]} -name .svn -type d -prune -o ( ${EXPR[@]} ) $ACTION, Điều này mang lại cho tôi đầu ra sau:find -type f -name .svn -type d -prune -o ( -true ) -print
Ingo Fischer

5

Chỉ cần nghĩ rằng tôi sẽ thêm một giải pháp thay thế đơn giản cho các bài đăng của Kaleb và những người khác (trong đó nêu chi tiết việc sử dụng find -prunetùy chọn ack, repofindcác lệnh , v.v.) đặc biệt áp dụng cho cách sử dụng mà bạn đã mô tả trong câu hỏi (và bất kỳ cách sử dụng tương tự nào khác):

  1. Để đạt hiệu quả, bạn nên luôn luôn cố gắng sử dụng find ... -exec grep ... +(nhờ Kenji để chỉ ra điều này) hoặc find ... | xargs egrep ...(xách tay) hoặc find ... -print0 | xargs -0 egrep ...(GNU; công trình trên tên tập tin chứa khoảng trắng) thay vì của find ... -exec grep ... \;.

    Biểu mẫu find ... -exec ... +find | xargsbiểu mẫu không phân nhánh egrepcho mỗi tệp mà thay vào đó là một loạt các tệp tại một thời điểm, dẫn đến việc thực thi nhanh hơn nhiều .

  2. Khi sử dụng find | xargsbiểu mẫu, bạn cũng có thể sử dụng grepđể dễ dàng và nhanh chóng cắt tỉa .svn(hoặc bất kỳ thư mục hoặc biểu thức chính quy nào), tức là find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...(hữu ích khi bạn cần một cái gì đó nhanh chóng và không thể bận tâm để nhớ cách thiết lập logic findcủa nó -prune.)

    Cách find | grep | xargstiếp cận tương tự như tùy chọn findcủa GNU -regex(xem ghostdog74bài của), nhưng dễ mang theo hơn (cũng sẽ hoạt động trên các nền tảng findkhông có GNU .)


1
@Vlad: Xin lưu ý rằng có hai hình thức cho -execchuyển đổi trong find: một là kết thúc bằng ;và một là kết thúc bằng +. Một kết thúc với +thay thế {}bởi một danh sách tất cả các tập tin phù hợp. Bên cạnh đó, regex của bạn cũng '/\.svn'khớp với tên tệp '.svn.txt'. Vui lòng tham khảo ý kiến ​​của tôi cho câu hỏi để biết thêm thông tin.
Siu Ching Pong -Asuka Kenji-

2
@Vlad: Đây là tiêu chuẩn POSIX cho findtiện ích. Xin vui lòng xem -execphần :-).
Siu Ching Pong -Asuka Kenji-

4

Trong kho lưu trữ mã nguồn, tôi thường chỉ muốn làm mọi thứ với các tệp văn bản.

Dòng đầu tiên là tất cả các tệp, ngoại trừ các tệp lưu trữ CVS, SVN và GIT.

Dòng thứ hai không bao gồm tất cả các tệp nhị phân.

find . -not \( -name .svn -prune -o -name .git -prune -o -name CVS -prune \) -type f -print0 | \
xargs -0 file -n | grep -v binary | cut -d ":" -f1

3

Tôi sử dụng find với các tùy chọn -not -path. Tôi đã không có may mắn với mận.

find .  -name "*.groovy" -not -path "./target/*" -print

sẽ tìm thấy các tệp Groovy không có trong đường dẫn thư mục đích.


3

Để giải quyết vấn đề này, bạn chỉ cần sử dụng điều kiện tìm này:

find \( -name 'messages.*' ! -path "*/.svn/*" \) -exec grep -Iw uint {} +

Bạn có thể thêm nhiều hạn chế như thế này:

find \( -name 'messages.*' ! -path "*/.svn/*" ! -path "*/CVS/*" \) -exec grep -Iw uint {} +

Bạn có thể tìm thêm thông tin về điều này trong phần trang "Toán tử": http://unixhelp.ed.ac.uk/CGI/man-cgi?find


3

Lưu ý rằng nếu bạn làm

find . -type f -name 'messages.*'

sau đó -printđược ngụ ý khi toàn bộ biểu thức ( -type f -name 'messages.*') là đúng, vì không có "hành động" (như -exec).

Trong khi, để dừng giảm dần vào một số thư mục nhất định, bạn nên sử dụng bất cứ thứ gì khớp với các thư mục đó và theo dõi nó -prune(điều này nhằm ngăn chặn việc giảm dần vào các thư mục); như vậy

find . -type d -name '.svn' -prune

Điều này đánh giá là True cho các thư mục .svn và chúng ta có thể sử dụng ngắn mạch boolean bằng cách làm theo điều này bởi -o(OR), sau đó phần tiếp theo sau -ochỉ được kiểm tra khi phần đầu tiên là Sai, do đó không phải là thư mục .svn. Nói cách khác, như sau:

find . -type d -name '.svn' -prune -o -name 'message.*' -exec grep -Iw uint {}

sẽ chỉ đánh giá những gì là đúng của -o, cụ thể là -name 'message.*' -exec grep -Iw uint {}, đối với các tệp KHÔNG có trong các thư mục .svn.

Lưu ý rằng vì .svncó thể luôn luôn là một thư mục (và không phải là một tệp) và trong trường hợp này chắc chắn không khớp với tên 'tin nhắn. *', Bạn cũng có thể bỏ qua -type dvà làm:

find . -name '.svn' -prune -o -name 'message.*' -exec grep -Iw uint {}

Cuối cùng, lưu ý rằng nếu bạn bỏ qua bất kỳ hành động nào ( -execlà một hành động), hãy nói như vậy:

find . -name '.svn' -prune -o -name 'message.*'

sau đó -printhành động được ngụ ý nhưng sẽ áp dụng cho biểu thức WHOLE, bao gồm cả -name '.svn' -prune -ophần và do đó in tất cả các thư mục .svn cũng như các tệp 'message. *', có thể không phải là những gì bạn muốn. Do đó, bạn luôn phải sử dụng một 'hành động' ở phía bên phải của biểu thức boolean khi sử dụng -prunetheo cách này. Và khi hành động đó được in, bạn phải thêm nó một cách rõ ràng, như vậy:

find . -name '.svn' -prune -o -name 'message.*' -print


2

Hãy thử findrepo , một trình bao bọc đơn giản xung quanh find / grep và nhanh hơn nhiều so với ack Bạn sẽ sử dụng nó trong trường hợp này như:

findrepo uint 'messages.*'

2

wcfind là tập lệnh tìm trình bao bọc mà tôi sử dụng để tự động xóa các thư mục .svn.


1

Điều này làm việc cho tôi trong dấu nhắc Unix

gfind. \ (-không -wholename '* \. Svn *' \) -type f -name 'tin nhắn. *' -exec grep -Iw uint {} +

Lệnh trên sẽ liệt kê các PHIM không có .svn và thực hiện grep mà bạn đã đề cập.


'gfind' là một lỗi đánh máy? Tôi không có nó trên Ubuntu 14.04.
Jonathan Hartley

Giả sử bạn có nghĩa là 'tìm thấy', điều này không hoàn toàn hiệu quả. Nó cũng lọc ra các tập tin như xxx.svnxxx. Điều này rất quan trọng - ví dụ: nếu bạn đang sử dụng git thay vì svn, bạn sẽ thường muốn bao gồm các tệp như .gitignore (không phải là siêu dữ liệu, đó là một tệp thông thường được bao gồm trong repo) trong kết quả tìm thấy.
Jonathan Hartley

1

tôi thường dẫn đầu ra thông qua grep một lần nữa để loại bỏ .svn, trong quá trình sử dụng của tôi, nó không chậm hơn nhiều. ví dụ điển hình:

find -name 'messages.*' -exec grep -Iw uint {} + | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'

HOẶC LÀ

find . -type f -print0 | xargs -0 egrep messages. | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.