Bagaimana saya bisa mendapatkan `find` untuk mengabaikan direktori .svn?


227

Saya sering menggunakan findperintah untuk mencari melalui kode sumber, menghapus file, apa pun. Anehnya, karena Subversion menyimpan duplikat dari setiap file di .svn/text-base/direktori -nya, pencarian sederhana saya akhirnya mendapatkan banyak hasil duplikat. Sebagai contoh, saya ingin mencari uintsecara berulang dalam beberapa file messages.hdan messages.cpp:

# 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;

Bagaimana saya bisa mengatakan finduntuk mengabaikan .svndirektori?


Pembaruan : Jika Anda memutakhirkan klien SVN Anda ke versi 1.7 ini tidak lagi menjadi masalah.

Fitur utama dari perubahan yang diperkenalkan pada Subversion 1.7 adalah sentralisasi penyimpanan metadata copy pekerjaan ke satu lokasi. Alih-alih .svndirektori di setiap direktori dalam copy pekerjaan, Subversion 1.7 copy pekerjaan hanya memiliki satu .svndirektori — di root copy pekerjaan. Direktori ini termasuk (antara lain) database yang didukung SQLite yang berisi semua metadata yang dibutuhkan Subversion untuk copy pekerjaan itu.


4
Untuk kinerja, coba gunakan find ... -print0 | xargs -0 egrep ...sebagai gantinya find ... -exec grep ...(tidak bercabang grepuntuk setiap file, tetapi untuk banyak file sekaligus). Dengan menggunakan formulir ini, Anda juga dapat memangkas .svndirektori tanpa menggunakan -pruneopsi find, yaitufind ... -print0 | egrep -v '/\.svn' | xargs -0 egrep ...
vladr

3
@ Vlad: Sejauh yang saya tahu, menggunakan -execdengan +tidak garpu grepuntuk setiap file, saat menggunakannya dengan ;tidak. Menggunakan -execsebenarnya lebih benar daripada menggunakan xargs. Harap perhatikan bahwa perintah seperti lsmelakukan sesuatu bahkan jika daftar argumen kosong, sementara perintah seperti chmodmemberikan kesalahan jika ada argumen yang tidak mencukupi. Untuk melihat apa yang saya maksud, hanya mencoba perintah berikut di direktori yang tidak memiliki shell script: find /path/to/dir -name '*.sh' -print0 | xargs -0 chmod 755. Bandingkan dengan yang satu ini: find /path/to/dir -name '*.sh' -exec chmod 755 '{}' '+'.
Siu Ching Pong -Asuka Kenji-

2
@Vlad: Selain itu, grepkeluar .svnjuga bukan ide yang bagus. Sementara findkhusus untuk menangani file properti, greptidak. Dalam contoh Anda, file bernama '.svn.txt' juga akan difilter oleh egrepperintah Anda . Meskipun Anda dapat memodifikasi regex Anda menjadi '^ / \. Svn $' , itu masih bukan praktik yang baik untuk melakukannya. The -prunepredikat findkarya sempurna untuk menyaring file (oleh nama file, atau penciptaan timestamp, atau kondisi apa pun yang Anda disediakan). Ini seperti bahkan jika Anda dapat membunuh seekor kecoa menggunakan pedang besar tidak berarti itu adalah cara yang disarankan untuk melakukannya :-).
Siu Ching Pong -Asuka Kenji-

3
Beralih ke Git memperbaiki masalah ini (di antara banyak lainnya). Dalam hanya membuat folder .git di root dari copy pekerjaan, tidak di setiap folder seperti SVN. Selain itu, folder .git tidak berisi file biasa yang akan dikacaukan dengan file Anda yang sebenarnya dengan nama yang sama.
Tronic

3
2Dan Moulding: svn 1.7 hanya membuat direktori .svn tingkat atas
ccpizza

Jawaban:


65

Untuk pencarian, dapatkah saya menyarankan Anda melihat ACK ? Ini adalah kode sumber yang disadari find, dan karena itu akan secara otomatis mengabaikan banyak jenis file, termasuk info repositori kode sumber seperti di atas.


3
Saya suka acksangat banyak, tetapi saya telah menemukan itu secara substansial lebih lambat dari find -type f -name "*.[ch]" | xargs grepketika berhadapan dengan basis kode besar.
John Ledbetter

63
John, saya penulis ack, dan jika Anda bisa memberi saya detail masalah kecepatan ack vs grep, saya akan menghargainya. Mereka benar-benar sebanding dalam semua kasus yang saya temukan. Baik beri tahu saya di github.com/petdance/ack/issues atau kirim email kepada saya di andy di petdance.com. Bahasa thans.
Andy Lester

63
Guys, itu tip, tapi jelas bukan jawaban untuk pertanyaan itu! :)
dolzenko

8
Bukankah ackditagih sebagai yang lebih baik grep, bukan sumber-sadar find? Beberapa contoh menggunakannya untuk menggantikan findakan membuat ini jawaban nyata.
michiakig

3
Itu adalah jawaban untuk pertanyaan yang dia tidak tahu dia tanyakan. =)
Frungi

293

kenapa tidak adil?

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

Predikat -not meniadakan segala sesuatu yang memiliki .svn di mana saja di jalan.

Jadi dalam kasus Anda itu akan menjadi

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

5
+1 super besar untuk "-not" dan "-iwholename". Ack luar biasa dan saya menggunakannya, tetapi find / exec masih memiliki kegunaannya.
David Blevins

9
Satu-satunya jawaban yang benar-benar menjawab pertanyaan awal.
Brendon Crawford

14
Saya jauh dari elemen saya dan saya yakin saya akan dikritik karena komentar ini, tetapi ternyata -tidak dan -nama yang dicuri tidak sesuai dengan POSIX. Saya menggunakan! sebagai ganti -not dan -path menggantikan -iwholename dan mendapatkan hasil yang sama. Menurut halaman manual saya (Ubuntu 12.04), sintaks ini kompatibel dengan POSIX.
John

1
@whaley Anda mengatakan '*.svn*'pada awalnya tapi kemudian '*.svn'. Mana yang benar Apakah keduanya berfungsi? Saya pikir mungkin seharusnya begitu '*.svn*'?
Keith M

1
@KeithM tangkapan hebat sebenarnya. Jawaban ini telah duduk di sini selama bertahun-tahun dan saya tidak berpikir ada yang menangkapnya sampai sekarang.
whaley

141

Sebagai berikut:

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

Atau, sebagai alternatif berdasarkan direktori dan bukan awalan jalur:

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

14
@ Kaleb: Hai. Saya sarankan find . -type d -name .svn -prune -o -printkarena sedikit lebih cepat. Menurut standar POSIX , ekspresi dievaluasi satu per satu, dalam urutan yang ditentukan. Jika ekspresi pertama -aadalah false, ekspresi kedua tidak akan dievaluasi (juga disebut hubungan pendek dan evaluasi ).
Siu Ching Pong -Asuka Kenji-

2
@ Kaleb: Sebagai membandingkan jenis file (setara dengan menguji apakah bit diatur dalam bilangan bulat) lebih cepat daripada membandingkan nama file (setara dengan perbandingan string, yaitu O (n)), menempatkan -type dsebelum -name .svnsecara teoritis lebih efisien. Namun, biasanya tidak signifikan kecuali jika Anda memiliki pohon direktori yang sangat besar.
Siu Ching Pong -Asuka Kenji-

5
@ SiuChingPong-AsukaKenji- tidak, hanya membandingkan nama file lebih cepat karena -type membutuhkan panggilan stat (2) pada setiap file. Nama file, bagaimanapun, adalah bagian dari respons readdir (3).
hraban

3
@JonathanHartley Anda melewatkan bagian -printsebagai ekspresi terakhir. Sesuatu seperti find . -name .git -prune -o \( -type f -name LICENSE -print \)bekerja seperti yang diharapkan.
sschuberth

1
Jika Anda ingin mengabaikan .git dan .svn dan hanya daftar direktori lain find . -name .svn -prune -o -name .git -prune -o -type d -print,. Mungkin beberapa milidetik lebih cepat menempatkan -type dsebelum keduanya -name, tetapi tidak sepadan dengan mengetik tambahan.
JPaget

34

Untuk mengabaikan .svn, .gitdan direktori tersembunyi lainnya (dimulai dengan titik), coba:

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

Namun, jika tujuan penggunaan findmencari di dalam file, Anda dapat mencoba menggunakan perintah ini:

  • git grep - perintah yang dirancang khusus untuk mencari pola dalam repositori Git.
  • ripgrep- yang secara default mengabaikan file tersembunyi dan file yang ditentukan dalam .gitignore.

Terkait: Bagaimana cara menemukan semua file yang mengandung teks tertentu di Linux?


Jawaban terbaik imo. Yang lain mencoba menjelaskan hal-hal yang tidak menjawab pertanyaan sederhana.
Anthony

19

Inilah yang akan saya lakukan dalam kasus Anda:

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

rgrepPerintah bawaan Emacs mengabaikan .svndirektori, dan banyak lagi file yang mungkin Anda tidak tertarik ketika melakukan find | grep. Inilah yang digunakan secara default:

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

Ini mengabaikan direktori yang dibuat oleh sebagian besar sistem kontrol versi, serta file yang dihasilkan untuk banyak bahasa pemrograman. Anda bisa membuat alias yang menjalankan perintah ini dan mengganti finddan greppola untuk masalah spesifik Anda.


12

GNU temukan

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

Saya sedang memuat jalur direktori ke dalam array untuk diproses oleh PHP. Jawaban lain yang lebih tinggi (untuk alasan apa pun) tidak memfilter file yang ditemukan (terlepas dari -type d) - jawaban ini berhasil. +1
be hollenbeck

11

Saya menggunakan grep untuk tujuan ini. Letakkan ini di ~ / .bashrc Anda

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

grep secara otomatis menggunakan opsi ini pada doa


1
Perlu dicatat bahwa 'grep' hanya memperoleh opsi '--exclude-dir' satu atau dua tahun yang lalu. Distribusi Linux terbaru menyertakannya, tetapi jika saya ingat dengan benar saya harus mengkompilasi grep saya sendiri (atau meminta homebrew untuk melakukannya) di OSX.
Jonathan Hartley

Saya menggunakan varian minor ini. .Bashrc saya membuat fungsi Bash 'grp', yang didefinisikan sebagai GREP_OPTIONS=xxx grep "$@". Ini berarti bahwa variabel GREP_OPTIONS hanya diset untuk instance grep yang saya jalankan secara manual menggunakan 'grp'. Ini berarti saya tidak pernah mendapatkan situasi di mana saya menjalankan alat, dan secara internal ia menyebut grep, tetapi alat tersebut menjadi bingung karena grep tidak berperilaku seperti yang diharapkan. Juga, saya memiliki fungsi kedua 'grpy', yang memanggil 'grp', tetapi menambahkan --include=*.py, hanya mencari file Python.
Jonathan Hartley

Sebenarnya, pada refleksi, melakukannya dengan cara saya tidak perlu lagi menggunakan GREP_OPTIONS sama sekali. Saya sekarang hanya memiliki fungsi shell 'grp' yang memanggil grep --exclude=tags --exclude_dir=.git ...etc... "$@". Saya suka bahwa ini berjalan seperti 'ack', tetapi saya mempertahankan kesadaran, dan mengendalikan, apa yang dilakukannya.
Jonathan Hartley

9

find . | grep -v \.svn


Anda harus melarikan diri .di .svnregexp.
vladr

4
Gunakan --fix-string dengan grep: | fgrep -v /.svn/atau `| grep F v / svn / `untuk mengecualikan persis direktori dan tidak file dengan "Svn" sebagai bagian dari nama mereka.
Stephen P

8

Mengapa Anda tidak mem-pipe perintah Anda dengan grep yang mudah dimengerti:

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

Anda harus melarikan diri .di .svnregexp.
vladr

@Yclian tanpa bayangan keraguan; jika tidak, direktori yang disebut 'tsvn', '1svn', 'asvn' dll. juga akan diabaikan sejak '.' adalah wildcard regexp: 'cocok dengan karakter apa saja'.
vladr

Baiklah, saya pikir itu hanya akan terjadi pada kasus -E dan -G. Saya baru saja diuji, salah saya. :(
yclian

2
Saya suka jawaban ini karena secara konseptual lebih sederhana daripada yang lain. Saya tidak dapat mengingat sintaks konyol untuk penggunaan 'find', tetapi saya pasti ingat bagaimana menggunakan grep -v karena digunakan dalam banyak situasi.
mattismyname

8

Buat skrip bernama ~/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

Script ini berperilaku identik dengan findperintah biasa tetapi memangkas .svndirektori. Kalau tidak, tingkah lakunya identik.

Contoh:

# 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;

Script ini tidak berfungsi seperti yang saya harapkan. Saat menjalankannya dengan "svnfind -type f", ia juga mencetak svn-directories dan file-file di svn-directories
Ingo Fischer

@ ifischer Bisakah Anda menambahkan echoperintah find dan beri tahu saya perintah apa yang dijalankan? svnfind -type fbekerja sangat baik pada mesin Red Hat saya.
John Kugelman

Ok jadi sepertinya tergantung OS. Saya menjalankan Debian Squeeze (sama di Ubuntu). Saya tidak mengerti apa yang Anda maksud dengan "tambahkan gema"?
Ingo Fischer

@ Ifischer Ubah baris terakhir menjadi echo find "${OPTIONS[@]}"...sehingga mencetak perintah find bukannya benar-benar menjalankannya.
John Kugelman

Ok mengubah baris terakhir menjadi echo find ${OPTIONS[@]} ${PATHS[@]} -name .svn -type d -prune -o ( ${EXPR[@]} ) $ACTION, Ini memberi saya output berikut:find -type f -name .svn -type d -prune -o ( -true ) -print
Ingo Fischer

5

Hanya berpikir saya akan menambahkan alternatif sederhana untuk posting Kaleb dan orang lain (yang merinci penggunaan find -pruneopsi ack,, repofindperintah , dll.) Yang khususnya berlaku untuk penggunaan yang telah Anda jelaskan dalam pertanyaan (dan penggunaan serupa lainnya):

  1. Untuk kinerja, Anda harus selalu mencoba untuk menggunakan find ... -exec grep ... +(terima kasih Kenji untuk menunjukkan ini) atau find ... | xargs egrep ...(portable) atau find ... -print0 | xargs -0 egrep ...(GNU; bekerja pada nama file yang mengandung spasi) bukan dari find ... -exec grep ... \;.

    Bentuk find ... -exec ... +dan find | xargstidak bercabang egrepuntuk setiap file, tetapi untuk sekelompok file sekaligus, menghasilkan eksekusi yang jauh lebih cepat .

  2. Bila menggunakan find | xargsformulir Anda juga dapat menggunakan grepdengan mudah dan cepat prune .svn(atau direktori atau ekspresi reguler), yaitu find ... -print0 | grep -v '/\.svn' | xargs -0 egrep ...(berguna ketika Anda perlu sesuatu yang cepat dan tidak dapat diganggu untuk mengingat cara mengatur find's -prunelogika.)

    The find | grep | xargsPendekatan ini mirip dengan GNU find's -regexpilihan (lihat ghostdog74' s post), tetapi lebih portabel (juga akan bekerja pada platform di mana GNU findtidak tersedia.)


1
@Vlad: Harap perhatikan bahwa ada dua formulir untuk -execberalih find: satu berakhir dengan ;dan yang lainnya berakhir dengan +. Yang berakhir dengan +diganti {}dengan daftar semua file yang cocok. Selain itu, regex Anda juga '/\.svn'cocok dengan nama file '.svn.txt'. Silakan merujuk komentar saya ke pertanyaan untuk informasi lebih lanjut.
Siu Ching Pong -Asuka Kenji-

2
@Vlad: Ini adalah standar POSIX untuk findutilitas. Silakan lihat -execbagian :-).
Siu Ching Pong -Asuka Kenji-

4

Dalam repositori kode sumber, saya biasanya ingin melakukan hal-hal hanya pada file teks.

Baris pertama adalah semua file, tidak termasuk file repositori CVS, SVN, dan GIT.

Baris kedua tidak termasuk semua file biner.

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

Saya menggunakan find dengan opsi -not -path. Saya belum beruntung dengan pangkas.

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

akan menemukan file asyik tidak di jalur direktori target.


3

Untuk mengatasi masalah ini, Anda cukup menggunakan kondisi pencarian ini:

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

Anda dapat menambahkan lebih banyak batasan seperti ini:

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

Anda dapat menemukan informasi lebih lanjut tentang ini di bagian halaman manual "Operator": http://unixhelp.ed.ac.uk/CGI/man-cgi?find


3

Perhatikan bahwa jika Anda melakukannya

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

maka -printtersirat ketika seluruh ekspresi ( -type f -name 'messages.*') benar, karena tidak ada 'tindakan' (seperti -exec).

Sementara, untuk berhenti turun ke direktori tertentu, Anda harus menggunakan apa pun yang cocok dengan direktori tersebut dan mengikutinya -prune(yang dimaksudkan untuk berhenti turun ke direktori); seperti itu:

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

Ini mengevaluasi ke True untuk direktori .svn, dan kita dapat menggunakan hubung singkat boolean dengan mengikuti ini dengan -o(OR), setelah itu apa yang mengikuti setelah -ohanya diperiksa ketika bagian pertama adalah False, maka itu bukan direktori .svn. Dengan kata lain, berikut ini:

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

hanya akan mengevaluasi apa yang benar -o, yaitu -name 'message.*' -exec grep -Iw uint {}, untuk file TIDAK di dalam direktori .svn.

Perhatikan bahwa karena .svnkemungkinan selalu merupakan direktori (dan bukan misalnya file), dan dalam hal ini tentu saja tidak cocok dengan nama 'pesan. *', Anda mungkin meninggalkan -type ddan lakukan:

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

Akhirnya, perhatikan bahwa jika Anda menghilangkan tindakan ( -exectindakan), katakan seperti:

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

maka -printtindakan tersirat tetapi akan berlaku untuk ekspresi SELURUH, termasuk -name '.svn' -prune -obagian dan dengan demikian mencetak semua direktori .svn serta file 'pesan. *', yang mungkin bukan yang Anda inginkan. Karenanya Anda harus selalu menggunakan 'aksi' di sisi kanan ekspresi boolean saat menggunakan -prunecara ini. Dan ketika tindakan itu dicetak, Anda harus menambahkannya secara eksplisit, seperti:

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


2

Coba findrepo yang merupakan pembungkus sederhana sekitar find / grep dan jauh lebih cepat daripada ack Anda akan menggunakannya dalam kasus ini seperti:

findrepo uint 'messages.*'

2

wcfind adalah skrip wrapper find yang saya gunakan untuk secara otomatis menghapus direktori .svn.


1

Ini berfungsi untuk saya di prompt Unix

temukan. Pesan \ (-tidak -dikenal '* \. svn *' \) -type f -name '. *' -exec grep -Iw uint {} +

Perintah di atas akan mencantumkan FILES yang tidak dengan .svn dan lakukan grep yang Anda sebutkan.


Apakah 'gfind' salah ketik? Saya tidak memilikinya di Ubuntu 14.04.
Jonathan Hartley

Anggap Anda bermaksud 'menemukan', ini tidak cukup berhasil. Ini juga menyaring file seperti xxx.svnxxx. Ini penting - misalnya jika Anda menggunakan git bukan svn, Anda akan sering ingin memasukkan file seperti .gitignore (yang bukan metadata, ini adalah file biasa yang termasuk dalam repo) dalam hasil dari find.
Jonathan Hartley

1

saya biasanya menyalurkan output melalui grep sekali lagi menghapus .svn, dalam penggunaan saya tidak jauh lebih lambat. contoh khas:

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

ATAU

find . -type f -print0 | xargs -0 egrep messages. | grep -Ev '.svn|.git|.anythingElseIwannaIgnore'
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.