Lijst met bestanden uitsluiten van zoeken

Als ik een lijst met bestandsnamen in een tekstbestand heb die ik wil uitsluiten wanneer ik finduitvoer, hoe kan ik dat dan doen? Ik wil bijvoorbeeld iets doen als:

find /dir -name "*.gz" -exclude_from skip_files

en haal alle .gz-bestanden in /dir behalve de bestanden die worden vermeld in skip_files. Maar find heeft geen vlag -exclude_from. Hoe kan ik alle bestanden in skip_filesoverslaan?


Antwoord 1, autoriteit 100%

Ik denk niet dat findeen optie als deze heeft, je zou een commando kunnen bouwen met printfen je lijst met uitsluitingen:

find /dir -name "*.gz" $(printf "! -name %s " $(cat skip_files))

Wat hetzelfde is als doen:

find /dir -name "*.gz" ! -name first_skip ! -name second_skip .... etc

U kunt ook van findnaar greppipetten:

find /dir -name "*.gz" | grep -vFf skip_files

Antwoord 2, autoriteit 58%

Dit is wat ik gewoonlijk doe om enkele bestanden uit het resultaat te verwijderen (in dit geval zocht ik naar alle tekstbestanden maar was niet geïnteresseerd in een heleboel valgrind memcheck-rapporten die we hier en daar hebben):

find . -type f -name '*.txt' ! -name '*mem*.txt'

Het lijkt te werken.


Antwoord 3, autoriteit 13%

Ik denk dat je het kunt proberen, zoals

find /dir \( -name "*.gz" ! -name skip_file1 ! -name skip_file2 ...so on \)

Antwoord 4, autoriteit 5%

find /var/www/test/ -type f \( -iname "*.*" ! -iname  "*.php" ! -iname "*.jpg" ! -iname "*.png"  \)

Het bovenstaande commando geeft een lijst van alle bestanden behalve bestanden met de extensie .php, .jpg ang .png. Deze opdracht werkt voor mij in stopverf.


Antwoord 5, autoriteit 5%

De grep-oplossing van Josh Jolly werkt, maar heeft O(N**2) complexiteit, waardoor het te traag is voor lange lijsten. Als de lijsten eerst worden gesorteerd (O(N*log(N)) complexiteit), kunt u commgebruiken, die O(N) complexiteit heeft:

find /dir -name '*.gz' |sort >everything_sorted
sort skip_files >skip_files_sorted
comm -23 everything_sorted skip_files_sorted | xargs . . . etc

mande commvan je computer voor details.


Antwoord 6

Deze oplossing doorloopt alle bestanden (niet exact uitgesloten van de opdracht find), maar produceert een uitvoer waarbij bestanden worden overgeslagen uit een lijst met uitsluitingen.
Ik vond dat handig tijdens het uitvoeren van een tijdrovende opdracht (file /dir -exec md5sum {} \;).

  1. Je kunt een shellscript maken om de logica voor overslaan af te handelen en commando’s uitvoeren op de gevonden bestanden (maak het uitvoerbaar met chmod, vervang echodoor andere commando’s):
   $ cat skip_file.sh
    #!/bin/bash
    found=$(grep "^$1$" files_to_skip.txt)
    if [ -z "$found" ]; then
        # run your command
        echo $1
    fi
  1. Maak een bestand met de lijst met bestanden die u wilt overslaan met de naam files_to_skip.txt(in de map van waaruit u actief bent).

  2. Gebruik dan find om het te gebruiken:

   find /dir -name "*.gz" -exec ./skip_file.sh {} \;

Other episodes