linux - tab - ubuntu terminal titel




So schließen Sie ein Verzeichnis in der Suche aus. Befehl (20)

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

Hier ist der Suchcode, den wir verwenden.

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

Das funktioniert, weil TESTS die Dateien für das Muster " * foo * " finden:

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

aber es funktioniert nicht , wenn Sie kein Muster verwenden ( FIND überprüft die Datei nicht). So find seine früher bewerteten " echten " & " falschen " Bools nicht. Beispiel für nicht funktionierenden Anwendungsfall mit obiger Schreibweise:

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

Es gibt keine TESTS! 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 es zu vergleichen oder besser nicht zu passen. Benutzen Sie in diesem Fall etwas wie:

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


Das ist für mich auf einem Mac geeignet:

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

Es schließt vendor und app/cache Verzeichnis für den Suchnamen aus, der mit php .


Dies ist das Format, das ich verwendet habe, um einige Pfade auszuschließen:

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

Ich habe damit alle Dateien gefunden, die nicht in ". *" Pfaden liegen:

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

Dies ist der einzige, der für mich funktioniert hat.

Suche nach "NameOfFile" mit Ausnahme von "Directory". Betonen Sie die Sterne *.

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

Es gibt viele gute Antworten, ich brauchte nur etwas Zeit, um zu verstehen, wofür jedes Element des Befehls und die Logik dahinter standen.

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

find beginnt, Dateien und Verzeichnisse im aktuellen Verzeichnis zu finden, daher der find . .

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

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

Jedes Verzeichnis oder jede Datei, die nicht das Verzeichnis ./misc ist , übergibt nicht den ersten -path ./misc . Aber sie werden gegen den zweiten Ausdruck getestet werden. Wenn ihr Name dem Muster *.txt sie wegen der Option -print gedruckt.

Wenn find das Verzeichnis ./misc erreicht, erfüllt dieses Verzeichnis nur den ersten Ausdruck. Also wird die Option -prune darauf angewendet. Es teilt dem Befehl find mit, dieses Verzeichnis nicht zu durchsuchen. So wird jede Datei oder jedes Verzeichnis in ./misc nicht einmal von find untersucht, wird nicht gegen den zweiten Teil des Ausdrucks getestet und nicht gedruckt.


Für FreeBSD Benutzer:

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

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 Verzeichnisses dir1.

Benutzen:

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

... um dir1 UND dir2 auszuschließen


Hier besteht eindeutig Verwirrung darüber, wie die bevorzugte Syntax zum Überspringen eines Verzeichnisses aussehen sollte.

GNU Meinung

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

Aus der GNU find man-Seite

Argumentation

-prune stoppt beim Abstieg in ein Verzeichnis. -not -path wird der -not -path immer noch in das übersprungene Verzeichnis -not -path , aber -not -path ist immer falsch, wenn find jede Datei testet.

Probleme mit -prune

-prune macht, was es beabsichtigt, aber sind immer noch einige Dinge, um die Sie sich kümmern müssen, wenn Sie es verwenden.

  1. find druckt das bereinigte Verzeichnis.

    • WAHR Das ist beabsichtigtes Verhalten, es geht einfach nicht hinein. Um zu vermeiden, dass das Verzeichnis vollständig gedruckt wird, verwenden Sie eine Syntax, die es logisch auslässt.
  2. -prune funktioniert nur mit -print und anderen Aktionen.

    • NICHT WAHR . -prune funktioniert mit allen Aktionen außer " -delete . Warum funktioniert das nicht mit delete? Für -delete zu arbeiten, muss das Verzeichnis in der DFS-Reihenfolge -delete werden, da -delete zuerst die Blätter, dann die Eltern der Blätter usw. -prune Aber um -prune sinnvoll zu definieren, muss find treffen Verzeichnis und stoppe absteigend, was bei -depth oder -delete eindeutig keinen Sinn -delete .

Performance

Ich habe einen einfachen Test der drei oben aufgewerteten Antworten zu dieser Frage eingerichtet (ersetzte -print mit -exec bash -c 'echo $0' {} \; um ein anderes Aktionsbeispiel -exec bash -c 'echo $0' {} \; ). 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

Sowohl die Syntax von f10bit als auch die Syntax von Daniel C. Sobral benötigten im Durchschnitt 10-25ms. GetFree's Syntax , die -prune nicht verwendet, dauerte 865ms. Also, das ist ein ziemlich extremes Beispiel, aber wenn Sie sich um die Laufzeit kümmern und etwas -prune intensives tun, sollten Sie -prune .

Beachten Sie, dass die Syntax von Daniel C. Sobral die bessere der beiden -prune Syntaxen war; aber ich vermute stark, dass dies das Ergebnis von etwas Caching ist, da die Reihenfolge, in der die beiden rannten, zum entgegengesetzten Ergebnis führte, während die Nicht-Prune-Version immer am langsamsten war.

Testskript

#!/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

Ich fand den Namen der Funktionen in C-Quellen-Dateien auszuschließen * .o und auszuschließen * .swp und auszuschließen (nicht reguläre Datei) und Dir-Ausgabe mit diesem Befehl ausschließen:

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

Ich finde das Folgende leichter zu verstehen als andere vorgeschlagene Lösungen:

find build -not \( -path build/external -prune \) -name \*.js

Das kommt von einem tatsächlichen Anwendungsfall, bei dem ich Yui-Compressor für einige von Wintersmith erzeugte Dateien aufrufen musste, aber andere Dateien weglassen musste, die unverändert gesendet werden mussten.

Inside \( und \) ist ein Ausdruck, der exakt mit build/external übereinstimmt und bei Erfolg vermeidet, etwas darunter zu durchlaufen . Dies wird dann als einzelner Ausdruck mit der Escape-Klammer gruppiert und mit dem Präfix -not was dazu führt, find alles -not wird, was mit diesem Ausdruck übereinstimmt.

Man könnte fragen, ob das Hinzufügen -not alle anderen Dateien, die durch -prune versteckt sind, -prune , und die Antwort ist nein. Die Art -prune Weise, wie -prune funktioniert, ist, dass alle Dateien, die unter diesem Verzeichnis liegen, permanent ignoriert werden.

Dies ist auch einfach erweiterbar, um zusätzliche Ausschlüsse hinzuzufügen. Beispielsweise:

find build -not \( -path build/external -prune \) -not \( -path build/blog -prune \) -name \*.js

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

Die große Idee ist, den Macintosh HD zu durchsuchen, aber zu vermeiden, alle externen Volumes zu durchlaufen, die meistens Time Machine-Backups, Imagesicherungen, gemountete Freigaben und Archive sind, ohne sie alle unmounten zu müssen, was oft unpraktisch ist.

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

#!/usr/bin/env bash
# inspired by http://.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 Archiv-Volumes, Time Machine, virtuellen Maschinen, anderen gemounteten Servern und so weiter zu tun. Einige der Volume-Namen enthalten Leerzeichen.

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


Ich habe mit find eine Liste von Dateien für xgettext und wollte ein bestimmtes Verzeichnis und seinen Inhalt weglassen. Ich habe viele Permutationen von -path kombiniert mit -prune , konnte aber das Verzeichnis, das ich -prune , nicht vollständig ausschließen.

Obwohl ich in der Lage war, den Inhalt des Verzeichnisses zu ignorieren, das ich ignorieren wollte, gab find dann das Verzeichnis selbst als eines der Ergebnisse zurück, was dazu xgettext , dass xgettext abstürzte (akzeptiert keine Verzeichnisse; nur Dateien).

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

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

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


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

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

Ich habe das here


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

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

Oder die umgekehrte grep "grep -v" -Option:

find -iname example.com | grep -v beta

Sie können detaillierte Anweisungen und Beispiele im Linux-Suchbefehl finden und Verzeichnisse von der Suche ausschließen .


Verwenden Sie besser die exec Aktion als die for Schleife:

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

Die exec ... '{}' ... '{}' \; wird für jede übereinstimmende Datei einmal ausgeführt und ersetzt die Klammern '{}' durch den aktuellen Dateinamen.

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

Anmerkungen

* Im Abschnitt Beispiele der find (GNU findutils) 4.4.2 man page


Verwenden Sie den Prune-Schalter, wenn Sie zum Beispiel das misc Verzeichnis ausschließen möchten, fügen -path ./misc -prune -o einfach einen -path ./misc -prune -o zu Ihrem find-Befehl 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 dir3 aus, da es in find Ausdrücken eine Aktion ist, die auf das Kriterium -path dir1 -o -path dir2 -o -path dir3 (wenn dir1 oder dir2 oder dir3) wirkt, mit dem type -d UND-verknüpft . Weitere Aktion ist -o print , nur drucken.


Wenn -prune nicht für Sie funktioniert, wird dies:

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

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

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

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


how-to-use-prune-option-of-find-in-sh ist eine ausgezeichnete Antwort von Laurence Gonsalves auf die 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 das Eingeben von /path/to/seach/ mehrmals zu vermeiden, wickeln Sie den find in ein pushd .. popd Paar.

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

 find . -name '*.js' -\! -name 'glob-for-excluded-dir' -prune




find