كيفية استخدام '-Prune' خيار "البحث" في sh؟
سؤال
أنا لا أفهم ذلك تماما الواردة من man find
, ، هل يمكن لأي شخص أن يعطيني بعض الأمثلة والتفسيرات؟ هل يمكنني الجمع بين التعبير المنتظم فيه؟
السؤال الأكثر تفصيلا هو مثل هذا:
اكتب نص شل، changeall
, ، والتي لديها واجهة مثل changeall [-r|-R] "string1" "string2"
. وبعد سوف تجد جميع الملفات مع لاحقة .h
, .C
, .cc
, ، أو .cpp
وتغيير جميع تكرارات string1
ل string2
. -r
هو خيار للبقاء في دير الحالي فقط أو بما في ذلك SUBDIR.
ملاحظة:
- للحالة غير العودية،
ls
غير مسموح به، يمكننا فقط استخدامfind
وsed
. - حاولت
find -depth
لكنه لم يكن مدعوما. لهذا السبب كنت أتساءل إذا-prune
يمكن أن تساعد، لكنها لم تفهم المثال منman find
.
Edit2: كنت أفعل المهمة، لم أسأل السؤال في تفاصيل كبيرة لأنني أرغب في الانتهاء من ذلك بنفسي. منذ أن فعلت ذلك بالفعل وتسليمها، الآن يمكنني ذكر السؤال بأكمله. أيضا، تمكنت من إنهاء المهمة دون استخدام -prune
, ولكن أود أن أتعلم ذلك على أي حال.
المحلول
الشيء الذي كنت قد وجدت مربكا عنه -prune
هو أنه عمل (مثل -print
)، وليس اختبار (مثل -name
). يغير قائمة "To Do"، ولكن دائما إرجاع صحيح.
النمط العام لاستخدام -prune
هذا هو:
find [path] [conditions to prune] -prune -o \
[your usual conditions] [actions to perform]
أنت دائما تريد دائما -o
(منطقي أو) مباشرة بعد -prune
, ، لأن هذا الجزء الأول من الاختبار (حتى بما في ذلك -prune
) سيعود خاطئة بالنسبة للأشياء التي تريدها فعلا (أي: الأشياء التي لا تريد أن تقلص).
إليك مثال:
find . -name .snapshot -prune -o -name '*.foo' -print
سيجد هذا ملفات "* .Foo" التي ليست تحت أدلة ".snapshot". في هذا المثال، -name .snapshot
يشكل [conditions to prune]
, ، و -name '*.foo' -print
يكون [your usual conditions]
و [actions to perform]
.
ملاحظات هامة:
إذا كان كل ما تريد القيام به هو طباعة النتائج التي قد تستخدمها لإخراج
-print
عمل. أنت عموما لا تريد أن تفعل ذلك عند استخدام-prune
.السلوك الافتراضي للعثور هو "و" بأكمله التعبير مع
-print
العمل إذا لم تكن هناك إجراءات أخرى غير-prune
(من المفارقات) في النهاية. وهذا يعني أن كتابة هذا:find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS
أي ما يعادل كتابة هذا:
find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
مما يعني أنه سوف يطبع أيضا اسم الدليل الذي تشوهات، والذي عادة ليس ما تريد. بدلا من ذلك من الأفضل تحديد ذلك بشكل صريح
-print
العمل إذا كان هذا ما تريد:find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS
إذا حدث "حالتك المعتادة" لتتناسب مع الملفات التي تطابق أيضا شرط PRUNE الخاص بك، فإن تلك الملفات سوف ليس أن تدرج في الإخراج. الطريق لإصلاح هذا هو إضافة
-type d
المسند لحالة القطع الخاصة بك.على سبيل المثال، لنفترض أننا أردنا تقليل أي دليل بدأ
.git
(من المسلم به هذا مفهومة إلى حد ما - عادة ما تحتاج فقط إلى إزالة الشيء المسمى بالضبط.git
)، ولكن بخلاف ذلك أراد أن يرى جميع الملفات، بما في ذلك الملفات مثل.gitignore
. وبعد قد تحاول هذا:find . -name '.git*' -prune -o -type f -print # DON'T DO THIS
هذا سيكون ليس تتضمن
.gitignore
في الإخراج. إليك النسخة الثابتة:find . -type d -name '.git*' -prune -o -type f -print # DO THIS
نصيحة إضافية: إذا كنت تستخدم إصدار جنو من find
, ، صفحة Texinfo ل find
لديه شرح أكثر تفصيلا من manpage (كما هو صحيح بالنسبة لمعظم مرافق جنو).
نصائح أخرى
حذار أن -برون لا يمنع تنازلي أي دليل كما قال البعض. يمنع تنازلي في الدلائل التي تتطابق مع الاختبار المطبق عليها. ربما سيساعد بعض الأمثلة (انظر أسفل مثال Regex). آسف لهذا كونها طويلة جدا.
$ find . -printf "%y %p\n" # print the file type the first time FYI
d .
f ./test
d ./dir1
d ./dir1/test
f ./dir1/test/file
f ./dir1/test/test
d ./dir1/scripts
f ./dir1/scripts/myscript.pl
f ./dir1/scripts/myscript.sh
f ./dir1/scripts/myscript.py
d ./dir2
d ./dir2/test
f ./dir2/test/file
f ./dir2/test/myscript.pl
f ./dir2/test/myscript.sh
$ find . -name test
./test
./dir1/test
./dir1/test/test
./dir2/test
$ find . -prune
.
$ find . -name test -prune
./test
./dir1/test
./dir2/test
$ find . -name test -prune -o -print
.
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2
$ find . -regex ".*/my.*p.$"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test/myscript.pl
$ find . -name test -prune -regex ".*/my.*p.$"
(no results)
$ find . -name test -prune -o -regex ".*/my.*p.$"
./test
./dir1/test
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test
$ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
$ find . -not -regex ".*test.*" .
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2
عادة الطريقة الأصلية التي نقوم بها الأشياء في لينكس والطريقة التي نعتقد أنها من اليسار إلى اليمين.
لذلك سوف تذهب واكتب ما تبحث عنه أولا:
find / -name "*.php"
ثم ربما تضغط على المدخل وأدرك أنك تحصل على العديد من الملفات من الدلائل التي ترغب في ذلك. دعونا نستبعد / وسائل الإعلام لتجنب البحث عن محركات الأقراص المثبتة.
يجب عليك الآن إلحاق ما يلي فقط بالأمر السابق:
-print -o -path '/media' -prune
لذلك الأمر النهائي هو:
find / -name "*.php" -print -o -path '/media' -prune
............... | <--- تشمل ---> | .................... | <- -------- باستثناء ---------> |
أعتقد أن هذا الهيكل أسهل بكثير ويرتبط بالنهج الصحيح
إضافة إلى النصيحة المقدمة في إجابات أخرى (ليس لدي ممثل لإنشاء ردود) ...
عند الجمع -prune
مع تعبيرات أخرى، هناك اختلاف دقيق في السلوك اعتمادا على التعبيرات الأخرى المستخدمة.
ستجد مثال Laurence Gonsalves ملفات "* .Foo" التي ليست تحت أدلة ".snapshot": -
find . -name .snapshot -prune -o -name '*.foo' -print
ومع ذلك، هذه الإرادة القصيرة مختلفة قليلا، ربما عن غير قصد، قائمة أيضا .snapshot
الدليل (وأي أدلة متداخلة .snapshot): -
find . -name .snapshot -prune -o -name '*.foo'
السبب هو (وفقا ل WanPage على نظامي): -
إذا كان التعبير المحدد لا يحتوي على أي من عمليات الانتخابات التمهيدية -EXEC أو -LS أو -OK أو -Print، يتم استبدال التعبير المعطى بفعالية ب:
(adite_expression) -
وهذا هو، المثال الثاني هو ما يعادل دخول ما يلي، وبالتالي تعديل تجميع المصطلحات: -
find . \( -name .snapshot -prune -o -name '*.foo' \) -print
وقد شودا هذا على الأقل على Solaris 5.10. بعد أن استخدمت نكهات مختلفة من * Nix لمدة 10 سنوات تقريبا، فقد بحثت مؤخرا عن سبب يحدث هذا.
Prunce هي عدم الانصهار في أي مفتاح دليل.
من صفحة الرجل
إذا لم يعط، صحيح؛ إذا كان الملف دليلا، فلا تنحدر فيه. إذا تم إعطاء -depth، خطأ؛ بدون تأثير.
في الأساس لن نغفز إلى أي دلائل فرعية.
خذ هذا المثال:
لديك الدلائل التالية
- / الصفحة الرئيسية / Test2
- / الرئيسية / test2 / test2
اذا ركضت find -name test2
:
سيعيد كل من الدلاريخ
اذا ركضت find -name test2 -prune
:
سيعود فقط / الصفحة الرئيسية / Test2 لأنها لن تنحدر إلى / الصفحة الرئيسية / Test2 للعثور على / الصفحة الرئيسية / Test2 / Test2
أنا لا خبير في هذا (وهذه الصفحة كانت مفيدة للغاية مع http://mywiki.wooledg.org/usingfind.)
فقط لاحظت -path
هو للمسار الذي تطابق تماما السلسلة / المسار الذي يأتي بعد find
(.
في أمثلة الرسائل) أينما -name
يطابق جميع الأسماء الأساسية.
find . -path ./.git -prune -o -name file -print
كتل دليل .git في الدليل الحالي الخاص بك ( كما الاكتشاف الخاص بك في .
)
find . -name .git -prune -o -name file -print
كتل جميع الدلائل الفرعية .git بشكل متكرر.
لاحظ ال ./
هو مهم للغاية! -path
يجب أن تطابق مسار الراسية .
أو كل ما يأتي بعد العثور عليها إذا حصلت على التطابقات معها (من الجانب الآخر من أو "-o
") ربما لا يوجد متذكير! كنت غير مدرك للغاية لهذا ووضعني باستخدام -Path عندما يكون رائعا عندما لا ترغب في تقليم جميع الدليل الفرعي بنفس الاسم البصري: D
إظهار كل شيء بما في ذلك Dir نفسه ولكن ليس محتوياتها المملية الطويلة:
find . -print -name dir -prune
إذا قرأت كل الإجابات الجيدة هنا فهمي الآن هو أن كل ما يلي إرجاع نفس النتائج:
find . -path ./dir1\* -prune -o -print
find . -path ./dir1 -prune -o -print
find . -path ./dir1\* -o -print
#look no prune at all!
ولكن آخر واحد سوف يستغرق وقتا أطول بكثير لأنه لا يزال يبحث عن كل شيء في DIR1. أعتقد أن السؤال الحقيقي هو كيفية -or
النتائج غير المرغوب فيها دون البحث في الواقع.
لذلك أعتقد أن القحول لا يعني عدم وضع مبارات الماضية ولكن بمناسبة لها كما فعلت ...
http://www.gnu.org/software/findutils/manual/html_mono/find.html."لكن هذا لا يرجع إلى تأثير الإجراء" -prune "(الذي يمنع فقط النزول فقط، فإنه لا يتأكد من أننا نتجاهل هذا البند). بدلا من ذلك، هذا التأثير يرجع إلى استخدام" -o ". نظرا لأن الجانب الأيسر من حالة "أو" نجحت في ./src/emacs، ليس من الضروري تقييم الجانب الأيمن ("-print") على الإطلاق لهذا الملف المحدد. "
find
يبني قائمة الملفات. ينطبق المسند الذي توفره لكل واحد وإرجاع تلك التي تمر.
هذه الفكرة مفادها أن -prune
يعني الاستبعاد من النتائج كان مربكا حقا بالنسبة لي. يمكنك استبعاد ملف دون تقليم:
find -name 'bad_guy' -o -name 'good_guy' -print // good_guy
الجميع -prune
هل يغير سلوك البحث. إذا كانت المباراة الحالية دليل، فتقول "يا find
, ، هذا الملف الذي تطابقك فقط، لا تنحدر فيه ". وبعد فقط يزيل هذه الشجرة (ولكن ليس الملف نفسه) من قائمة الملفات للبحث.
يجب اسمه -dont-descend
.