Hoe een directory in find uit te sluiten. commando

Ik probeer een find-opdracht uit te voeren voor alle JavaScript-bestanden, maar hoe sluit ik een specifieke map uit?

Hier is de findcode die we gebruiken.

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

Antwoord 1, autoriteit 100%

Gebruik de schakelaar -prune. Als u bijvoorbeeld de directory miscwilt uitsluiten, voegt u gewoon een -path ./misc -prune -otoe aan uw find-opdracht:

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

Hier is een voorbeeld met meerdere mappen:

find . -type d \( -path dir1 -o -path dir2 -o -path dir3 \) -prune -false -o -name '*.txt'

Hier sluiten we ./dir1, ./dir2en ./dir3uit in de huidige directory, aangezien in find-expressies het is een actie die werkt volgens de criteria -path dir1 -o -path dir2 -o -path dir3(indien dir1of dir2of dir3), ANDed met type -d.

Gebruik -nameom de directorynaam op elk niveau uit te sluiten:

find . -type d \( -name node_modules -o -name dir2 -o -path name \) -prune -false -o -name '*.json'

Antwoord 2, autoriteit 98%

Als -pruneniet voor u werkt, zal dit:

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

Voorbehoud:vereist het doorlopen van alle ongewenste mappen.


Antwoord 3, autoriteit 36%

Ik vind het volgende gemakkelijker om over te redeneren dan andere voorgestelde oplossingen:

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

Belangrijke opmerking:de paden die u typt na -pathmoeten exact overeenkomen met wat findzou afdrukken zonder de uitsluiting. Als deze zin verwarrend is, zorg er dan voor dat je volledige paden gebruikt door de opdracht heleals volgt: find /full/path/-not \( -path /full/path/exclude/this-prune \) .... Zie opmerking [1] voor een beter begrip.

In \(en \)is een uitdrukking die exactbuild/externalzal matchen (zie belangrijke opmerking hierboven), en zal, bij succes, vermijden om iets hieronder te doorkruisen. Dit wordt dan gegroepeerd als een enkele expressie met het escaped haakje, en voorafgegaan door -notwaardoor findalles overslaat dat overeenkomt met die expressie.

Je zou je kunnen afvragen of het toevoegen van -notniet alle andere bestanden die verborgen zijn door -pruneweer zullen verschijnen, en het antwoord is nee. De manier waarop -prunewerkt, is dat alles dat, zodra het is bereikt, de bestanden onder die map permanent worden genegeerd.

Dit komt van een daadwerkelijk gebruik, waarbij ik yui-compressor moest aanroepen voor sommige bestanden die door wintersmith waren gegenereerd, maar andere bestanden wegliet die ongewijzigd moeten worden verzonden.


OPMERKING [1] : als u /tmp/foo/barwilt uitsluiten en u wilt zoeken zoals deze “find /tmp \(...“DAN MOET U -path /tmp/foo/barSPECIFICEERD. Als u aan de andere kant vindt, vindt u als deze cd /tmp; find . \(...Dan moet u -path ./foo/bar.


4, Autoriteit 11%

Dit is de enige die voor mij werkte.

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

Zoeken naar “MyFile” exclusief “Directory”.
Geef de nadruk op de sterren *.


5, Autoriteit 5%

Eén optie zou zijn om alle resultaten uit te sluiten die de mapnaam met GRREP bevatten. Bijvoorbeeld:

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

6, Autoriteit 3%

Ik geef de voorkeur aan de -notnotatie … Het is meer leesbaar:

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

7, Autoriteit 2%

Gebruik de -prune-optie. Dus, zoiets als:

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

De ‘-type d -name proc -prune’ zoekt alleen naar mappen met de naam proc om uit te sluiten.
De ‘-o’ is een ‘OF’-operator.


Antwoord 8, autoriteit 2%

-prunewerkt zeker en is het beste antwoord omdat het voorkomt dat u afdaalt naar de map die u wilt uitsluiten. -not -pathdie nog steeds de uitgesloten map doorzoekt, maar het resultaat niet afdrukt, wat een probleem kan zijn als de uitgesloten map op het netwerkvolume is gemount of als u geen machtigingen hebt.

Het lastige is dat finderg kieskeurig is over de volgorde van de argumenten, dus als je ze niet precies goed krijgt, werkt je commando misschien niet. De volgorde van de argumenten is over het algemeen als volgt:

find {path} {options} {action}

{path}: plaats eerst alle aan het pad gerelateerde argumenten, zoals . -path './dir1' -prune -o

{options}: ik heb het meeste succes als ik -name, -iname, etcals laatste optie in deze groep zet. bijv. -type f -iname '*.js'

{action}: u wilt -printtoevoegen wanneer u -prune

gebruikt

Hier is een werkend voorbeeld:

# 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

Antwoord 9

Dit is de indeling die ik heb gebruikt om sommige paden uit te sluiten:

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

Ik heb dit gebruikt om alle bestanden te vinden die niet in “.*”-paden staan:

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

Antwoord 10

Er zijn veel goede antwoorden, het kostte me alleen wat tijd om te begrijpen waar elk element van de opdracht voor was en de logica erachter.

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

find begint met het zoeken naar bestanden en mappen in de huidige map, vandaar de find ..

De optie -ostaat voor een logische OR en scheidt de twee delen van het commando:

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

Elke map of elk bestand dat nietde ./misc-map is, zal het eerste test -path ./miscniet doorstaan. Maar ze zullen worden getoetst aan de tweede uitdrukking. Als hun naam overeenkomt met het patroon *.txtworden ze afgedrukt vanwege de optie -print.

Als find de map ./misc bereikt, voldoet deze map alleen aan de eerste uitdrukking. Dus de optie -prunewordt erop toegepast. Het vertelt het find commando om nietdie map te verkennen. Dus elk bestand of elke map in ./misc zal niet eens worden verkend door te vinden, zal niet worden getest tegen het tweede deel van de uitdrukking en zal niet worden afgedrukt.


Antwoord 11

De -path -prune-aanpak werkt ook met jokertekens in het pad. Hier is een find-instructie die de mappen zal vinden voor een git-server die meerdere git-opslagplaatsen bedient, waarbij de interne git-mappen worden weggelaten:

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 \)  

Antwoord 12

Meerdere mappen uitsluiten:

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

Om mappen toe te voegen, voegt u -o -path "./dirname/*":

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

Maar misschien moet je een gewone uitdrukkinggebruiken, als er veel mappen zijn om uit te sluiten.


Antwoord 13

een goede truc om te voorkomen dat de gesnoeide mappen worden afgedrukt, is om -printte gebruiken (werkt ook voor -exec) na de rechterkant van de -orna -prune. Bijvoorbeeld …

find . -path "*/.*" -prune -or -iname "*.j2"

drukt het pad af van alle bestanden onder de huidige map met de extensie `.j2′, waarbij alle verborgen mappen worden overgeslagen. Netjes. Maar het zal ook het volledige pad afdrukken van elke map die wordt overgeslagen, zoals hierboven vermeld. Het volgende echter niet, …

find . -path "*/.*" -prune -or -iname "*.j2" -print

omdat er logischerwijs een verborgen -andis achter de operator -inameen vóór de -print. Dit bindt het aan het rechtergedeelte van de -or-clausule vanwege de booleaanse volgorde van bewerkingen en associativiteit. Maar de documenten zeggen dat er een verborgen -printis als deze (of een van zijn neven … -print0, enz.) niet is gespecificeerd. Dus waarom is het linkerdeel van de -or-afdruk niet? Blijkbaar (en ik begreep dit niet toen ik de man-pagina voor het eerst las), is dat waar als er geen -print-of -execOVERAL is, waarin case, -print wordt logischerwijs rond gestrooid zodat alles wordt afgedrukt. Als zelfs maar EEN print-achtige bewerking in een clausule wordt uitgedrukt, verdwijnen al die verborgen logische en krijg je alleen wat je opgeeft. Eerlijk gezegd had ik het misschien liever andersom gehad, maar dan zou een findmet alleen beschrijvende operatoren blijkbaar niets uithalen, dus ik denk dat het logisch is zoals het is. Zoals hierboven vermeld, werkt dit allemaal ook met -exec, dus het volgende geeft een volledige ls -la-lijst voor elk bestand met de gewenste extensie, maar niet de eerste niveau van elke verborgen map, …

find . -path "*/.*" -prune -or -iname "*.j2" -exec ls -la -- {} +

Voor mij (en anderen in deze thread), wordt de syntaxis findvrij snel behoorlijk barok, dus ik gooi altijd haakjes tussen haakjes om er zeker van te zijn dat ik weet wat aan wat bindt, dus ik maak meestal een macro voor typbaarheid en vorm al dergelijke uitspraken als …

find . \( \( ... description of stuff to avoid ... \) -prune \) -or \
\( ... description of stuff I want to find ... [ -exec or -print] \)

Het is moeilijk om fout te gaan door de wereld op deze manier in twee delen op te zetten. Ik hoop dat dit helpt, hoewel het onwaarschijnlijk lijkt dat iemand om te lezen aan het 30 + TH-antwoord en stem op, maar men kan hopen. : -)


14

voor een werkoplossing (getest op ubuntu & nbsp; 12.04 (precieze pangolin)) …

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

Zoeken naar MP3-bestanden in de huidige map en submappen behalve in Dir1-submap.

Gebruik:

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

… om Dir1 en Dir2

uit te sluiten


15

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

lijkt hetzelfde te werken als

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

en is gemakkelijker om IMO te onthouden.


16

U kunt ook regelmatige uitdrukkingen gebruiken om sommige bestanden / dirs op te nemen / uitsluiten met iets dergelijks:

find . -regextype posix-egrep -regex ".*\.(js|vue|s?css|php|html|json)$" -and -not -regex ".*/(node_modules|vendor)/.*" 

Hiermee geeft u alleen alle JS, VUE, CSS, ETC-bestanden, maar exclusief alle bestanden in de node_modulesen vendorMAPPERS.


17

U kunt gebruik maken van de optie snoeien om dit te bereiken. Net als in bijvoorbeeld:

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

Of de inverse grep “grep -v” optie:

find -iname example.com | grep -v beta

Hier vind je gedetailleerde instructies en voorbeelden in de Linux find commando uit te sluiten directories van het zoeken .


Antwoord 18

find . \( -path '.**/.git' -o -path '.**/.hg' \) -prune -o -name '*.js' -print

Het bovenstaande voorbeeld vindt alle *.jsBestanden onder de huidige map, exclusief mappen .gitEN .hg, maakt niet uit hoe Diep deze .giten .hgmappen zijn.

Opmerking: dit werkt ook:

find . \( -path '.*/.git' -o -path '.*/.hg' \) -prune -o -name '*.js' -print

Maar ik geef de voorkeur aan de **notatie voor consistentie met een aantal andere tools die hier uit onderwerp zouden zijn.


19

Geen van eerdere antwoorden is goed op ubuntu.
Probeer dit:

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

Ik heb dit gevonden hier


20

Dit is geschikt voor mij op een Mac:

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

Het is uitsluiten vendoren app/cacheDIR VOOR ZOEKNAAM WELKELIJK MET ZIJN MET php.


21

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

22

De volgende opdrachten werkt:

find . -path ./.git -prune -o -print

Als u een probleem hebt met het vinden, gebruikt u de -D treeoptie om de expressie-analyse-informatie te bekijken.

find -D tree . -path ./.git -prune -o -print

Of de -D all, om alle uitvoeringsinformatie te zien.

find -D all . -path ./.git -prune -o -print

Antwoord 23

Als iemand onderzoekt hoe je meerdere paden tegelijk kunt negeren.
U kunt bash-arrays gebruiken (werkt perfect op GNU bash, versie 4.4.20(1)-release)

#!/usr/bin/env bash
# This script helps ignore unnecessary dir paths while using the find command
EXCLUDE_DIRS=(
    "! -path /*.git/*"
    "! -path /*go/*"
    "! -path /*.bundle/*"
    "! -path /*.cache/*"
    "! -path /*.local/*"
    "! -path /*.themes/*"
    "! -path /*.config/*"
    "! -path /*.codeintel/*"
    "! -path /*python2.7/*"
    "! -path /*python3.6/*"
    "! -path /*__pycache__/*"
)
find $HOME -type f ${EXCLUDE_DIRS[@]}
# if you like fzf
find $HOME -type f ${EXCLUDE_DIRS[@]} | fzf --height 40% --reverse

Ook om de een of andere reden kun je /bin/ directorypaden niet negeren.


Antwoord 24

Ik gebruikte findom een lijst met bestanden voor xgettextte leveren, en wilde een specifieke map en de inhoud ervan weglaten. Ik heb veel permutaties van -pathgecombineerd met -prunegeprobeerd, maar ik kon de map die ik weg wilde hebben niet volledig uitsluiten.

Hoewel ik de inhoudvan de map die ik wilde negeren kon negeren, retourneerde findvervolgens de map zelf als een van de resultaten, waardoor xgettextcrasht als resultaat (accepteert geen mappen; alleen bestanden).

Mijn oplossing was om gewoon grep -vte gebruiken om de map over te slaan die ik niet in de resultaten wilde hebben:

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

Of er een argument is voor finddat 100% zal werken, kan ik niet met zekerheid zeggen. Het gebruik van grepwas een snelle en gemakkelijke oplossing na wat hoofdpijn.


Antwoord 25

Voor degenen onder u met oudere versies van UNIX die -pathof -not

niet kunnen gebruiken

Getest op SunOS 5.10 bash 3.2 en SunOS 5.11 bash 4.4

find . -type f -name "*" -o -type d -name "*excluded_directory*" -prune -type f

Antwoord 26

hoe-te-gebruiken-prune-option-of-find-in-shis een uitstekend antwoord van Laurence Gonsalvesover hoe -prunewerkt.

En hier is de algemene oplossing:

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

Om te voorkomen dat u /path/to/seach/meerdere keren typt, wikkelt u de findin een pushd .. popd-paar.

p>

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

27

Ik heb het bevel hierboven geprobeerd, maar geen van degenen met behulp van “-prune” werkt voor mij.
Uiteindelijk heb ik dit geprobeerd met opdracht hieronder:

find . \( -name "*" \) -prune -a ! -name "directory"

Other episodes