it-swarm.com.de

So schließen Sie ein Verzeichnis in find aus. Befehl

Ich versuche, einen find -Befehl für alle JavaScript-Dateien auszuführen, aber wie schließe ich ein bestimmtes Verzeichnis aus?

Hier ist der find Code, den wir verwenden.

for file in $(find . -name '*.js')
do 
  Java -jar config/yuicompressor-2.4.2.jar --type js $file -o $file
done
1180
helion3

Verwenden Sie den Schalter -Prune. Wenn Sie beispielsweise das Verzeichnis misc ausschließen möchten, fügen Sie Ihrem find-Befehl einfach einen -path ./misc -Prune -o hinzu:

find . -path ./misc -Prune -o -name '*.txt' -print

Hier ist ein Beispiel mit mehreren Verzeichnissen:

find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -Prune -o -print

Hier schließen wir dir1, dir2 und dir aus, da es sich bei find Ausdrücken um eine Aktion handelt, die auf die Kriterien -path dir1 -o -path dir2 -o -path dir3 (if dir1 oder dir2 oder dir), UND-verknüpft mit type -d.

Weitere Aktion ist -o print, einfach ausdrucken.

922
f10bit

Wenn -Prune bei Ihnen nicht funktioniert, geschieht Folgendes:

find -name "*.js" -not -path "./directory/*"

Einschränkung: erfordert das Durchsuchen aller unerwünschten Verzeichnisse.

1783
GetFree

Ich finde Folgendes einfacher zu überlegen als andere vorgeschlagene Lösungen:

_find build -not \( -path build/external -Prune \) -name \*.js
# you can also exclude multiple paths
find build -not \( -path build/external -Prune \) -not \( -path build/blog -Prune \) -name \*.js
_

Wichtiger Hinweis: Die Pfade, die Sie nach _-path_ eingeben, müssen genau mit dem übereinstimmen, was find ohne den Ausschluss drucken würde. Wenn dieser Satz verwirrt, stellen Sie einfach sicher, dass Sie die vollständigen Pfade durch den ganzen Befehl wie folgt verwenden: find /full/path/ -not \( -path /full/path/exclude/this -Prune \) .... Siehe Anmerkung [1], wenn Sie ein besseres Verständnis wünschen.

Innerhalb von _\(_ und _\)_ ist ein Ausdruck, der genau mit _build/external_ übereinstimmt (siehe wichtigen Hinweis oben) wird im Erfolgsfall vermeiden, irgendetwas unter zu durchlaufen. Dies wird dann als einzelner Ausdruck mit der maskierten Klammer gruppiert und mit dem Präfix _-not_ versehen, sodass find alles überspringt, was mit diesem Ausdruck übereinstimmt.

Möglicherweise werden Sie gefragt, ob durch das Hinzufügen von _-not_ nicht alle anderen von _-Prune_ ausgeblendeten Dateien wieder angezeigt werden sollen. Die Antwort lautet "Nein". _-Prune_ funktioniert so, dass alle Dateien unterhalb dieses Verzeichnisses, sobald sie erreicht sind, dauerhaft ignoriert werden.

Dies kommt von einem tatsächlichen Anwendungsfall, in dem ich yui-compressor für einige von wintersmith erzeugte Dateien aufrufen musste, aber andere Dateien weglassen musste, die so wie sie sind gesendet werden mussten.


Anmerkung [1]: Wenn Sie _/tmp/foo/bar_ ausschließen möchten und "_find /tmp \(..._" ausführen, müssen Sie _-path /tmp/foo/bar_ angeben. Wenn Sie dagegen find like this _cd /tmp; find . \(..._ ausführen, müssen Sie _-path ./foo/bar_ angeben.

422

Hier besteht eindeutig eine gewisse Verwirrung darüber, wie die bevorzugte Syntax für das Überspringen eines Verzeichnisses aussehen sollte.

GNU Opinion

To ignore a directory and the files under it, use -Prune

Aus der GNU Manpage

Begründung

-Prune verhindert, dass find in ein Verzeichnis absteigt. Nur die Angabe von -not -path wird weiterhin in das Verzeichnis übersprungen abgelegt, aber -not -path ist immer dann falsch, wenn find jede Datei testet.

Probleme mit -Prune

-Prune macht das, was es soll, aber es gibt noch einige Dinge, auf die Sie achten müssen, wenn Sie es verwenden.

  1. find druckt das beschnittene Verzeichnis.

    • TRUE Das ist beabsichtigtes Verhalten, es steigt einfach nicht hinein. Verwenden Sie eine Syntax, die das Verzeichnis logisch weglässt, um das Drucken des gesamten Verzeichnisses zu vermeiden.
  2. -Prune funktioniert nur mit -print und keinen anderen Aktionen.

    • NICHT WAHR . -Prune funktioniert mit allen Aktionen außer -delete. Warum funktioniert es nicht mit delete? Damit -delete funktioniert, muss find das Verzeichnis in der DFS-Reihenfolge durchlaufen, da -delete zuerst die Blätter und dann die Eltern der Blätter usw. löscht Damit die Angabe von -Prune sinnvoll ist, muss find ein Verzeichnis treffen und nicht weiter absteigen, was bei aktivierter Option -depth oder -delete offensichtlich keinen Sinn ergibt.

Leistung

Ich habe einen einfachen Test der drei am besten bewerteten Antworten auf diese Frage erstellt (-print wurde durch -exec bash -c 'echo $0' {} \; ersetzt, um ein weiteres Aktionsbeispiel anzuzeigen). Ergebnisse sind unten

----------------------------------------------
# of files/dirs in level one directories
.performance_test/Prune_me     702702    
.performance_test/other        2         
----------------------------------------------

> find ".performance_test" -path ".performance_test/Prune_me" -Prune -o -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 23513814

> find ".performance_test" -not \( -path ".performance_test/Prune_me" -Prune \) -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 10670141

> find ".performance_test" -not -path ".performance_test/Prune_me*" -exec bash -c 'echo "$0"' {} \;
.performance_test
.performance_test/other
.performance_test/other/foo
  [# of files] 3 [Runtime(ns)] 864843145

Fazit

Die Ausführung von f10bits Syntax und Daniel C. Sobrals Syntax dauerte durchschnittlich 10-25 ms. GetFree's Syntax , das -Prune nicht verwendet, hat 865ms gedauert. Ja, dies ist ein ziemlich extremes Beispiel, aber wenn Sie sich für die Laufzeit interessieren und etwas Fernintensives tun, sollten Sie -Prune verwenden.

Anmerkung Daniel C. Sobrals Syntax hat die bessere der beiden -Prune -Syntaxen ausgeführt; Ich vermute jedoch sehr, dass dies das Ergebnis einer gewissen Zwischenspeicherung ist, da das Umschalten der Reihenfolge, in der die beiden ausgeführt wurden, zu einem entgegengesetzten Ergebnis führte, während die Nicht-Prune-Version immer am langsamsten war.

Test Script

#!/bin/bash

dir='.performance_test'

setup() {
  mkdir "$dir" || exit 1
  mkdir -p "$dir/Prune_me/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/w/x/y/z" \
    "$dir/other"

  find "$dir/Prune_me" -depth -type d -exec mkdir '{}'/{A..Z} \;
  find "$dir/Prune_me" -type d -exec touch '{}'/{1..1000} \;
  touch "$dir/other/foo"
}

cleanup() {
  rm -rf "$dir"
}

stats() {
  for file in "$dir"/*; do
    if [[ -d "$file" ]]; then
      count=$(find "$file" | wc -l)
      printf "%-30s %-10s\n" "$file" "$count"
    fi
  done
}

name1() {
  find "$dir" -path "$dir/Prune_me" -Prune -o -exec bash -c 'echo "$0"'  {} \;
}

name2() {
  find "$dir" -not \( -path "$dir/Prune_me" -Prune \) -exec bash -c 'echo "$0"' {} \;
}

name3() {
  find "$dir" -not -path "$dir/Prune_me*" -exec bash -c 'echo "$0"' {} \;
}

printf "Setting up test files...\n\n"
setup
echo "----------------------------------------------"
echo "# of files/dirs in level one directories"
stats | sort -k 2 -n -r
echo "----------------------------------------------"

printf "\nRunning performance test...\n\n"

echo \> find \""$dir"\" -path \""$dir/Prune_me"\" -Prune -o -exec bash -c \'echo \"\$0\"\'  {} \\\;
name1
s=$(date +%s%N)
name1_num=$(name1 | wc -l)
e=$(date +%s%N)
name1_perf=$((e-s))
printf "  [# of files] $name1_num [Runtime(ns)] $name1_perf\n\n"

echo \> find \""$dir"\" -not \\\( -path \""$dir/Prune_me"\" -Prune \\\) -exec bash -c \'echo \"\$0\"\' {} \\\;
name2
s=$(date +%s%N)
name2_num=$(name2 | wc -l)
e=$(date +%s%N)
name2_perf=$((e-s))
printf "  [# of files] $name2_num [Runtime(ns)] $name2_perf\n\n"

echo \> find \""$dir"\" -not -path \""$dir/Prune_me*"\" -exec bash -c \'echo \"\$0\"\' {} \\\;
name3
s=$(date +%s%N)
name3_num=$(name3 | wc -l)
e=$(date +%s%N)
name3_perf=$((e-s))
printf "  [# of files] $name3_num [Runtime(ns)] $name3_perf\n\n"

echo "Cleaning up test files..."
cleanup
192
BroSlow

Eine Möglichkeit wäre, alle Ergebnisse, die den Verzeichnisnamen enthalten, mit grep auszuschließen. Zum Beispiel:

find . -name '*.js' | grep -v excludeddir
60
Joshua

Dies ist die einzige, die für mich gearbeitet hat.

find / -name NameOfFile ! -path '*/Directory/*'

Suche nach "NameOfFile" ohne "Directory". Sterne betonen *.

47
DimiDak

Ich bevorzuge die -not -Notation ... sie ist besser lesbar:

find . -name '*.js' -and -not -path directory
41
mpapis

Verwenden Sie die Option -Prune. So etwas wie:

find . -type d -name proc -Prune -o -name '*.js'

Der '-type d -name proc -Prune' sucht nur nach Verzeichnissen mit dem Namen proc, die ausgeschlossen werden sollen.
Das '-o' ist ein 'OR'-Operator.

19
Drew Frezell

Dies ist das Format, mit dem ich einige Pfade ausgeschlossen habe:

$ find ./ -type f -name "pattern" ! -path "excluded path" ! -path "excluded path"

Ich habe dies verwendet, um alle Dateien zu finden, die sich nicht in ". *" - Pfaden befinden:

$ find ./ -type f -name "*" ! -path "./.*" ! -path "./*/.*"
15
user1882879

-Prune funktioniert auf jeden Fall und ist die beste Antwort, da dadurch ein Abstieg in das Verzeichnis verhindert wird, das Sie ausschließen möchten. -not -path, bei dem das ausgeschlossene Verzeichnis weiterhin durchsucht wird, gibt das Ergebnis nur nicht aus. Dies kann ein Problem sein, wenn das ausgeschlossene Verzeichnis ein bereitgestelltes Netzwerkvolume ist oder Sie keine Berechtigungen haben.

Der schwierige Teil ist, dass find die Reihenfolge der Argumente sehr genau bestimmt. Wenn Sie sie also nicht richtig verstehen, funktioniert Ihr Befehl möglicherweise nicht. Die Reihenfolge der Argumente ist im Allgemeinen wie folgt:

find {path} {options} {action}

{path}: Setzen Sie alle pfadbezogenen Argumente an die erste Stelle, z. B. . -path './dir1' -Prune -o

{options}: Ich habe den größten Erfolg, wenn ich -name, -iname, etc als letzte Option in diese Gruppe stelle. Z.B. -type f -iname '*.js'

{action}: Sie möchten -print hinzufügen, wenn Sie -Prune verwenden.

Hier ist ein funktionierendes Beispiel:

# setup test
mkdir dir1 dir2 dir3
touch dir1/file.txt; touch dir1/file.js
touch dir2/file.txt; touch dir2/file.js
touch dir3/file.txt; touch dir3/file.js

# search for *.js, exclude dir1
find . -path './dir1' -Prune -o -type f -iname '*.js' -print

# search for *.js, exclude dir1 and dir2
find . \( -path './dir1' -o -path './dir2' \) -Prune -o -type f -iname '*.js' -print
14
wisbucky

Der -path -Prune-Ansatz funktioniert auch mit Platzhaltern im Pfad. Hier ist eine find-Anweisung, die die Verzeichnisse für einen Git-Server findet, der mehrere Git-Repositorys bedient, wobei die internen Git-Verzeichnisse weggelassen werden:

find . -type d \
   -not \( -path */objects -Prune \) \
   -not \( -path */branches -Prune \) \
   -not \( -path */refs -Prune \) \
   -not \( -path */logs -Prune \) \
   -not \( -path */.git -Prune \) \
   -not \( -path */info -Prune \) \
   -not \( -path */hooks -Prune \)  
10
Wolfgang Fahl

Es gibt viele gute Antworten. Ich habe nur einige Zeit gebraucht, um zu verstehen, wofür die einzelnen Elemente des Befehls und die dahinter stehende Logik bestimmt waren.

find . -path ./misc -Prune -o -name '*.txt' -print

find startet das Auffinden von Dateien und Verzeichnissen im aktuellen Verzeichnis, daher der find ..

Die Option -o steht für ein logisches OR und trennt die beiden Teile des Befehls:

[ -path ./misc -Prune ] OR [ -name '*.txt' -print ]

Alle Verzeichnisse oder Dateien, die nicht das Verzeichnis ./misc sind, bestehen den ersten Test -path ./misc nicht. Sie werden jedoch anhand des zweiten Ausdrucks getestet. Wenn ihr Name dem Muster *.txt entspricht, werden sie aufgrund der Option -print gedruckt.

Wenn find das Verzeichnis ./misc erreicht, erfüllt dieses Verzeichnis nur den ersten Ausdruck. Daher wird die Option -Prune darauf angewendet. Es weist den Befehl find an, nicht dieses Verzeichnis zu durchsuchen. Daher werden Dateien oder Verzeichnisse in ./misc nicht einmal von find durchsucht, nicht mit dem zweiten Teil des Ausdrucks verglichen und nicht gedruckt.

8
Istopopoki

So schließen Sie mehrere Verzeichnisse aus:

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" \)

Fügen Sie zum Hinzufügen von Verzeichnissen -o -path "./dirname/*" hinzu:

find . -name '*.js' -not \( -path "./dir1" -o -path "./dir2/*" -o -path "./dir3/*"\)

Aber vielleicht sollten Sie ein regulärer Ausdruck verwenden, wenn es viele auszuschließende Verzeichnisse gibt.

8
JBENOIT

Für eine funktionierende Lösung (getestet auf Ubuntu 12.04 (Precise Pangolin)) ...

find ! -path "dir1" -iname "*.mp3"

sucht nach MP3-Dateien im aktuellen Ordner und in den Unterordnern mit Ausnahme des Unterordners dir1.

Verwenden:

find ! -path "dir1" ! -path "dir2" -iname "*.mp3"

... um dir1 UND dir2 auszuschließen

7
james dupin

Sie können die Option Prune verwenden, um dies zu erreichen. Wie zum Beispiel:

find ./ -path ./beta/* -Prune -o -iname example.com -print

Oder die inverse grep "grep -v" Option:

find -iname example.com | grep -v beta

Detaillierte Anweisungen und Beispiele finden Sie in Linux find-Befehl, um Verzeichnisse von der Suche auszuschließen.

6
Siju V
find -name '*.js' -not -path './node_modules/*' -not -path './vendor/*'

scheint genauso zu funktionieren wie

find -name '*.js' -not \( -path './node_modules/*' -o -path './vendor/*' \)

und ist leichter zu merken, IMO.

4
Funkodebat

Für diejenigen von Ihnen unter älteren UNIX-Versionen, die - path oder - not nicht verwenden können

Getestet unter SunOS 5.10 Bash 3.2 und SunOS 5.11 Bash 4.4

find . -type f -name "*" -o -type d -name "*excluded_directory*" -Prune -type f
3
JaredTS486

TLDR: Verstehe deine Stammverzeichnisse und passe deine Suche von dort aus an, indem du die Option -path <excluded_path> -Prune -o verwendest. Fügen Sie am Ende des ausgeschlossenen Pfads keinen nachgestellten / ein.

Beispiel:

find / -path /mnt -Prune -o -name "*libname-server-2.a*" -print


Um find effektiv nutzen zu können, ist es meiner Meinung nach unerlässlich, die Verzeichnisstruktur Ihres Dateisystems genau zu verstehen. Auf meinem Heimcomputer sind Festplatten mit mehreren TB vorhanden, von denen ungefähr die Hälfte mit rsnapshot (d. H. rsync) gesichert wurde. Obwohl die Sicherung auf einem physisch unabhängigen (doppelten) Laufwerk erfolgt, wird es unter meinem Systemstammverzeichnis (/) eingehängt: /mnt/Backups/rsnapshot_backups/:

/mnt/Backups/
└── rsnapshot_backups/
    ├── hourly.0/
    ├── hourly.1/
    ├── ...
    ├── daily.0/
    ├── daily.1/
    ├── ...
    ├── weekly.0/
    ├── weekly.1/
    ├── ...
    ├── monthly.0/
    ├── monthly.1/
    └── ...

Das Verzeichnis /mnt/Backups/rsnapshot_backups/ belegt derzeit ~ 2,9 TB mit ~ 60 Millionen Dateien und Ordnern. Das einfache Durchsuchen dieser Inhalte nimmt Zeit in Anspruch:

## As Sudo (#), to avoid numerous "Permission denied" warnings:

time find /mnt/Backups/rsnapshot_backups | wc -l
60314138    ## 60.3M files, folders
34:07.30    ## 34 min

time du /mnt/Backups/rsnapshot_backups -d 0
3112240160  /mnt/Backups/rsnapshot_backups    ## 3.1 TB
33:51.88    ## 34 min

time rsnapshot du    ## << more accurate re: rsnapshot footprint
2.9T    /mnt/Backups/rsnapshot_backups/hourly.0/
4.1G    /mnt/Backups/rsnapshot_backups/hourly.1/
...
4.7G    /mnt/Backups/rsnapshot_backups/weekly.3/
2.9T    total    ## 2.9 TB, per Sudo rsnapshot du (more accurate)
2:34:54          ## 2 hr 35 min

Daher muss ich mich jedes Mal, wenn ich auf meiner / (Root) -Partition nach einer Datei suchen muss, mit dem Durchlaufen meiner Sicherungspartition befassen (wenn möglich vermeiden).


BEISPIELE

Unter den in diesem Thread verschiedentlich vorgeschlagenen Lösungsansätzen ( Ausschließen eines Verzeichnisses im Befehl find. ) finde ich, dass Suchen mit der akzeptierten Antwort viel schneller sind - mit Vorbehalten.

Lösung 1

Angenommen, ich möchte die Systemdatei libname-server-2.a finden, aber nicht meine rsnapshot Sicherungen durchsuchen. Verwenden Sie zum schnellen Auffinden einer Systemdatei den Ausschlusspfad /mnt (d. H. Verwenden Sie /mnt, nicht /mnt/ oder /mnt/Backups oder ...):

## As Sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt -Prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
real    0m8.644s              ## 8.6 sec  <<< NOTE!
user    0m1.669s
 sys    0m2.466s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt -Prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 3 sec     ## ~3 sec  <<< NOTE!

... findet diese Datei in wenigen Sekunden, während dies viel länger dauert (scheint sich durch alle "ausgeschlossenen" Verzeichnisse zu wiederholen):

## As Sudo (#), to avoid numerous "Permission denied" warnings:

time find / -path /mnt/ -Prune -o -name "*libname-server-2.a*" -print
find: warning: -path /mnt/ will not match anything because it ends with /.
/usr/lib/libname-server-2.a
real    33m10.658s            ## 33 min 11 sec (~231-663x slower!)
user    1m43.142s
 sys    2m22.666s

## As regular user (victoria); I also use an alternate timing mechanism, as
## here I am using 2>/dev/null to suppress "Permission denied" warnings:

$ START="$(date +"%s")" && find 2>/dev/null / -path /mnt/ -Prune -o \
    -name "*libname-server-2.a*" -print; END="$(date +"%s")"; \
    TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/usr/lib/libname-server-2.a
find command took 1775 sec    ## 29.6 min

Lösung 2

Die andere in diesem Thread angebotene Lösung ( SO # 4210042 ) weist ebenfalls eine schlechte Leistung auf:

## As Sudo (#), to avoid numerous "Permission denied" warnings:

time find / -name "*libname-server-2.a*" -not -path "/mnt"
/usr/lib/libname-server-2.a
real    33m37.911s            ## 33 min 38 sec (~235x slower)
user    1m45.134s
 sys    2m31.846s

time find / -name "*libname-server-2.a*" -not -path "/mnt/*"
/usr/lib/libname-server-2.a
real    33m11.208s            ## 33 min 11 sec
user    1m22.185s
 sys    2m29.962s

ZUSAMMENFASSUNG | SCHLUSSFOLGERUNGEN

Verwenden Sie den in "Solution 1" dargestellten Ansatz.

find / -path /mnt -Prune -o -name "*libname-server-2.a*" -print

d.h.

... -path <excluded_path> -Prune -o ...

beachten Sie, dass der Befehl find immer dann, wenn Sie den nachgestellten / zum ausgeschlossenen Pfad hinzufügen, rekursiv (alle diese) /mnt/* Verzeichnisse eingibt - in meinem Fall wegen des /mnt/Backups/rsnapshot_backups/* Unterverzeichnisse, enthält zusätzlich ~ 2.9 TB zu durchsuchende Dateien! Wenn kein abschließender / angehängt wird, sollte die Suche fast sofort (innerhalb von Sekunden) abgeschlossen sein.

"Lösung 2" (... -not -path <exclude path> ...) scheint ebenfalls die ausgeschlossenen Verzeichnisse rekursiv zu durchsuchen - wobei ausgeschlossene Übereinstimmungen nicht zurückgegeben werden, diese Suchzeit jedoch unnötig beansprucht wird.


Suche in diesen rsnapshot Backups:

So finden Sie eine Datei in einer meiner stündlichen/täglichen/wöchentlichen/monatlichen rsnapshot Sicherungen:

$ START="$(date +"%s")" && find 2>/dev/null /mnt/Backups/rsnapshot_backups/daily.0 -name '*04t8ugijrlkj.jpg'; END="$(date +"%s")"; TIME="$((END - START))"; printf 'find command took %s sec\n' "$TIME"
/mnt/Backups/rsnapshot_backups/daily.0/snapshot_root/mnt/Vancouver/temp/04t8ugijrlkj.jpg
find command took 312 sec   ## 5.2 minutes: despite apparent rsnapshot size
                            ## (~4 GB), it is in fact searching through ~2.9 TB)

Ausgenommen ein verschachteltes Verzeichnis:

Hier möchte ich ein verschachteltes Verzeichnis ausschließen, z. /mnt/Vancouver/projects/ie/claws/data/* bei der Suche von /mnt/Vancouver/projects/:

$ time find . -iname '*test_file*'
./ie/claws/data/test_file
./ie/claws/test_file
0:01.97

$ time find . -path '*/data' -Prune -o -iname '*test_file*' -print
./ie/claws/test_file
0:00.07

Nebenbei: Durch Hinzufügen von -print am Ende des Befehls wird der Ausdruck des ausgeschlossenen Verzeichnisses unterdrückt:

$ find / -path /mnt -Prune -o -name "*libname-server-2.a*"
/mnt
/usr/lib/libname-server-2.a

$ find / -path /mnt -Prune -o -name "*libname-server-2.a*" -print
/usr/lib/libname-server-2.a
3
Victoria Stuart

Ich habe find verwendet, um eine Liste von Dateien für xgettext bereitzustellen, und wollte ein bestimmtes Verzeichnis und seinen Inhalt weglassen. Ich habe viele Permutationen von -path in Kombination mit -Prune ausprobiert, konnte jedoch das von mir gewünschte Verzeichnis nicht vollständig ausschließen.

Obwohl ich das Inhalt des Verzeichnisses, das ich ignorieren wollte, ignorieren konnte, gab find das Verzeichnis selbst als eines der Ergebnisse zurück, was dazu führte, dass xgettext als abstürzte result (akzeptiert keine Verzeichnisse; nur Dateien).

Meine Lösung bestand darin, einfach grep -v zu verwenden, um das Verzeichnis zu überspringen, das ich in den Ergebnissen nicht haben wollte:

find /project/directory -iname '*.php' -or -iname '*.phtml' | grep -iv '/some/directory' | xargs xgettext

Ob es für find ein Argument gibt, das zu 100% funktioniert, kann ich nicht mit Sicherheit sagen. Die Verwendung von grep war nach einigen Kopfschmerzen eine schnelle und einfache Lösung.

3
Lemmings19
find . -name '*.js' -\! -name 'glob-for-excluded-dir' -Prune
3

Verwendung von Prune Option of Find In Sh ist eine hervorragende Antwort von Laurence Gonsalves zur Funktionsweise von -Prune.

Und hier ist die generische Lösung:

find /path/to/search                    \
  -type d                               \
    \( -path /path/to/search/exclude_me \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -Prune                              \
  -o                                    \
  -type f -name '*\.js' -print

Um zu vermeiden, dass Sie /path/to/seach/ mehrmals eingeben, schließen Sie find in ein pushd .. popd -Paar ein.

pushd /path/to/search;                  \
find .                                  \
  -type d                               \
    \( -path ./exclude_me               \
       -o                               \
       -name exclude_me_too_anywhere    \
     \)                                 \
    -Prune                              \
  -o                                    \
  -type f -name '*\.js' -print;         \
 popd
2
go2null

Für das, was ich brauchte, funktionierte es wie folgt: Auf allen Servern wurde landscape.jpg gefunden, beginnend mit root, und die Suche in /var -Verzeichnis wurde ausgeschlossen:

find / -maxdepth 1 -type d | grep -v /var | xargs -I '{}' find '{}' -name landscape.jpg

find / -maxdepth 1 -type d listet alle d irectories in / auf

grep -v /var schließt `/ var 'aus der Liste aus

xargs -I '{}' find '{}' -name landscape.jpg Führe einen beliebigen Befehl wie find mit jedem Verzeichnis/Ergebnis aus der Liste aus

2
adrianTNT

Dies ist für mich auf einem Mac geeignet:

find . -name *.php -or -path "./vendor" -Prune -or -path "./app/cache" -Prune

Es werden vendor und app/cache Verzeichnis für den Suchnamen ausgeschlossen, die mit php versehen sind.

2
jiahut

Keine der vorherigen Antworten ist auf Ubuntu gut. Versuche dies:

find . ! -path "*/test/*" -type f -name "*.js" ! -name "*-min-*" ! -name "*console*"

Ich habe dies gefunden hier

2
sixro

Verwenden Sie besser die Aktion exec als die Schleife for:

find . -path "./dirtoexclude" -Prune \
    -o -exec Java -jar config/yuicompressor-2.4.2.jar --type js '{}' -o '{}' \;

Der exec ... '{}' ... '{}' \; wird einmal für jede übereinstimmende Datei ausgeführt, wobei die geschweiften Klammern '{}' durch den aktuellen Dateinamen ersetzt werden.

Beachten Sie, dass die geschweiften Klammern in einfache Anführungszeichen eingeschlossen sind, um sie vor der Interpretation als Shellskript-Interpunktion zu schützen*.


Anmerkungen

* Aus dem Abschnitt BEISPIELE der Manpage find (GNU findutils) 4.4.2

1
Alberto

Ich habe den obigen Befehl ausprobiert, aber keiner von denen, die "-Prune" verwenden, funktioniert für mich. Schließlich habe ich das mit dem folgenden Befehl ausprobiert:

find . \( -name "*" \) -Prune -a ! -name "directory"
1
Jolly Liu

Ich habe festgestellt, dass der Funktionsname in C-Quelldateien * .o ausschließt und * .swp ausschließt und (keine reguläre Datei) und dir-Ausgabe mit diesem Befehl ausschließt:

find .  \( ! -path "./output/*" \) -a \( -type f \) -a \( ! -name '*.o' \) -a \( ! -name '*.swp' \) | xargs grep -n soc_attach
1
Ivan Ivanovich

Ich bin mir nicht sicher, ob dies alle Edge-Fälle abdecken würde, aber das Folgende wäre ziemlich einfach und einfach zu versuchen:

ls -1|grep -v -e ddl -e docs| xargs rm -rf

Dies sollte alle Dateien/Verzeichnisse aus dem aktuellen Verzeichnis mit den Auszügen 'ddls' und 'docs' entfernen.

0
Arnab

Wenn Suchverzeichnisse Muster haben (in meinem Fall meistens); Sie können es einfach wie folgt machen:

find ./n* -name "*.tcl" 

Im obigen Beispiel; Es sucht in allen Unterverzeichnissen, die mit "n" beginnen.

0
Prince Bhanwra

Für FreeBSD Benutzer:

 find . -name '*.js' -not -path '*exclude/this/dir*'
0

Dies funktioniert, weil findTESTS die Dateien für das pattern " * foo * ":

find ! -path "dir1" ! -path "dir2" -name "*foo*"

aber es funktioniert NICHT wenn Sie kein Muster verwenden (find nicht TEST die Datei) . Daher verwendet find nicht das zuvor bewertete " true " & " false "bools. Beispiel für einen nicht funktionierenden Anwendungsfall mit der obigen Notation:

find ! -path "dir1" ! -path "dir2" -type f

Es gibt keine find PRÜFUNG! Wenn Sie also Dateien ohne Mustererkennung suchen müssen, verwenden Sie -Prune. Durch die Verwendung von Prune ist find immer schneller, während es diese Verzeichnisse wirklich überspringt, anstatt sie abzugleichen oder besser nicht abzugleichen. Verwenden Sie in diesem Fall etwa Folgendes:

find dir -not \( -path "dir1" -Prune \) -not \( -path "dir2" -Prune \) -type f

oder:

find dir -not \( -path "dir1" -o -path "dir2" -Prune \) -type f

Grüße

0
d0n

Ich habe die Vorschläge auf dieser Seite gefunden und viele andere Seiten funktionieren auf meinem Mac OS X-System einfach nicht. Ich habe jedoch eine Variante gefunden, die für mich funktioniert.

Die große Idee ist, den Macintosh HD zu durchsuchen, aber nicht alle externen Volumes zu durchlaufen, bei denen es sich hauptsächlich um Time Machine-Backups, Image-Backups, gemountete Freigaben und Archive handelt, ohne sie alle aushängen zu müssen, was häufig unpraktisch ist.

Hier ist mein Arbeitsskript, das ich "findit" genannt habe.

#!/usr/bin/env bash
# inspired by http://stackoverflow.com/questions/4210042/exclude-directory-from-find-command Danile C. Sobral
# using special syntax to avoid traversing. 
# However, logic is refactored because the Sobral version still traverses 
# everything on my system

echo ============================
echo find - from cwd, omitting external volumes
date
echo Enter Sudo password if requested
Sudo find . -not \( \
-path ./Volumes/Archive -Prune -o \
-path ./Volumes/Boot\ OS\ X -Prune -o \
-path ./Volumes/C \
-path ./Volumes/Data -Prune -o \
-path ./Volumes/jas -Prune -o \
-path ./Volumes/Recovery\ HD -Prune -o \
-path ./Volumes/Time\ Machine\ Backups -Prune -o \
-path ./Volumes/SuperDuper\ Image -Prune -o \
-path ./Volumes/userland -Prune \
\) -name "$1" -print
date
echo ============================
iMac2:~ jas$

Die verschiedenen Pfade haben mit externen Archivvolumes, Time Machine, virtuellen Maschinen, anderen gemounteten Servern usw. zu tun. Einige der Datenträgernamen enthalten Leerzeichen.

Ein guter Testlauf ist "findit index.php", da diese Datei auf meinem System an vielen Stellen vorkommt. Mit diesem Skript dauert es ungefähr 10 Minuten, um die Hauptfestplatte zu durchsuchen. Ohne diese Ausschlüsse dauert es viele Stunden.

0
Jeffrey Simon