Comment exclure / ignorer les fichiers et répertoires cachés dans une recherche "trouver" avec caractères génériques?

119

À partir de (remarquez les caractères génériques avant et après "du texte")

find . -type f -name '*some text*'

Comment peut-on exclure / ignorer tous les fichiers et répertoires cachés?

Cela fait trop longtemps que je googe dans Google . paramètres (point d’exclamation), mais aucun exemple approprié (et parcimonieux) qui a juste fonctionné .

La tuyauterie | à grepserait une option et j’aimerais aussi des exemples de cela; mais je m'intéresse surtout à une brève ligne unique (ou à deux lignes uniques, illustrant différentes manières d'atteindre le même objectif de ligne de commande), simplement à l' aide de find.

ps: Trouver des fichiers sous Linux et exclure des répertoires spécifiques semble étroitement lié, mais a) n'est pas encore accepté et b) est lié-mais-différent-et-distinct, mais c) peut être une source d'inspiration et permettre de mettre le doigt sur la confusion!

Modifier

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", travaux. La regex recherche "n'importe quoi, puis une barre oblique, puis un point, puis n'importe quoi" (c'est-à-dire tous les fichiers et dossiers cachés, y compris leurs sous-dossiers) et le "!" nie la regex.

noisette de natty
la source
N'aide pas avec ce que tu as demandé dans ton édition mais regarde ma question et sa réponse ici: unix.stackexchange.com/q/69164/15760 et aussi le lien dans la réponse.

Réponses:

134

Ceci imprime tous les fichiers qui sont les descendants de votre répertoire, en ignorant les fichiers et répertoires cachés:

find . -not -path '*/\.*'

Donc, si vous cherchez un fichier avec some textson nom et que vous voulez ignorer les fichiers et répertoires cachés, lancez:

find . -not -path '*/\.*' -type f -name '*some text*'

Explication:

L' -pathoption run vérifie qu'un modèle correspond à la chaîne de chemin d'accès complète. *est un caractère générique, /un séparateur de répertoire, \.un point (il doit être échappé pour éviter toute signification spéciale) et *un autre caractère générique. -notsignifie que ne sélectionnez pas les fichiers correspondant à ce test.

Je ne pense pas que ce findsoit assez intelligent pour éviter de rechercher récursivement les répertoires cachés dans la commande précédente, aussi si vous avez besoin de rapidité, utilisez -pruneplutôt, comme ceci:

 find . -type d -path '*/\.*' -prune -o -not -name '.*' -type f -name '*some text*' -print
Flimm
la source
Notez avec le dernier dont vous avez besoin -printà la fin! De plus, -name '\.*' would be more efficient instead of je ne sais pas si -path` (car le chemin recherche des sous-chemins, mais ceux-ci seront supprimés)
artfulrobot
Quelle est la signification particulière de .dans ce contexte?
frostschutz
@frostschutz Le point après findsignifie le répertoire actuel: findexaminera tous les fichiers et répertoires du répertoire actuel. L'argument suivant pathest une expression régulière, dans laquelle un point signifie normalement "n'importe quel caractère". Pour lui donner un point littéral, nous devons l'échapper avec une barre oblique inverse. L'argument après -name n'est pas une expression régulière, mais il étend les jokers comme ?et *comme le fait un shell.
Flimm
2
@frostschutz En fait, à bien y penser, je peux me tromper d' .avoir une signification spéciale.
Flimm
1
@ Flimm Yup, pas besoin de s'échapper .. Pour autant que je sache, que ceux - ci doivent être échappé: *, ?et [].
jeudi
10

C'est l'un des rares moyens d'exclure les fichiers de points qui fonctionnent également correctement sous BSD, Mac et Linux:

find "$PWD" -name ".*" -prune -o -print
  • $PWD affiche le chemin complet du répertoire actuel pour que le chemin ne commence pas par ./
  • -name ".*" -prune correspond à tous les fichiers ou répertoires qui commencent par un point, puis ne descendent pas
  • -o -printsignifie imprimer le nom du fichier si l'expression précédente ne correspond à rien. L'utilisation de -printou -print0empêche toutes les autres expressions de s'imprimer par défaut.
Eradman
la source
S'il vous plaît expliquer / élaborer sur "complexe alarmant"; les réponses déjà données et votre réponse semblent indiquer le contraire ...?
Noisette à propos de natty
2
"compliqué de manière alarmante" est probablement excessif. J'ai reformulé la réponse pour aller droit au but. Je pense que la réponse que j'ai publiée est difficile à comprendre et difficile à lire sans une lecture très attentive de la page de manuel. Si vous utilisez uniquement GNU find, il y a plus de solutions possibles.
eradman
-o ... -printest utile. Pour mon usage, je l’ai maintenant find ... '!' -name . -name '.*' -prune -o ... -print, ce qui était plus pratique que d’inclure $ PWD.
Roger Pate
4
find $DIR -not -path '*/\.*' -type f \( ! -iname ".*" \)

Exclut tous les répertoires cachés et les fichiers cachés sous $ DIR

client
la source
C'est la réponse parfaite. Il trouve tous les fichiers de manière récursive mais exclut les éléments de ligne des répertoires et des fichiers cachés. Merci!
KyleFarris
2

La réponse que j'avais initialement publiée en tant que "modification" de ma question initiale ci-dessus:

find . \( ! -regex '.*/\..*' \) -type f -name "whatever", travaux. La regex recherche "n'importe quoi, puis une barre oblique, puis un point, puis n'importe quoi" (c'est-à-dire tous les fichiers et dossiers cachés, y compris leurs sous-dossiers) et le "!" nie la regex.

noisette de natty
la source
Similaires, mais uniquement pour le dossier en cours:find . \( ! -regex './\..*' \) -type f -maxdepth 1 -print
phyatt
2

Vous n'êtes pas obligé d'utiliser findpour cela. Utilisez simplement globstar dans shell it-self, comme ceci:

echo **/*foo*

ou:

ls **/*foo*

**/représente n'importe quel dossier de manière récursive et *foo*n'importe quel fichier qui a fooson nom.

Par défaut, using lsimprimera les noms de fichiers à l’exclusion des fichiers et répertoires cachés.

Si vous n'avez pas activé la fonction de recherche, faites-le en shopt -s globstar.

Remarque: une nouvelle option de globbing fonctionne dans les shell Bash 4, zsh et similaires.


Exemple:

$ mkdir -vp a/b/c/d
mkdir: created directory 'a'
mkdir: created directory 'a/b'
mkdir: created directory 'a/b/c'
mkdir: created directory 'a/b/c/d'
$ touch a/b/c/d/foo a/b/c/d/bar  a/b/c/d/.foo_hidden a/b/c/d/foo_not_hidden
$ echo **/*foo*
a/b/c/d/foo  a/b/c/d/foo_not_hidden
Kenorb
la source
5
Vous n'avez pas besoin lsde ça! echo **/*foo*
Kevin Cox
@kenorb (et @ kevin-cox). Pourriez-vous être un peu plus prolixe? Pourquoi globstar (= *) travaillerait-il ici et comment? Que fait le slash / do?
Noisette à propos de natty
@nuttyaboutnatty /signifie dossier, il sépare les répertoires du nom de fichier. *représente fondamentalement tout.
Kenorb
@kenorb oui-mais: comment ce one-liner aide-t-il à résoudre la question initiale?
noisette sur natty
1
@nuttyaboutnatty Exemple clarifié et ajouté. Cela aide en trouvant des fichiers en ignorant celui qui est caché.
Kenorb
1

La réponse de @ Flimm est bonne, en particulier parce qu'elle empêche la recherche de descendre dans des répertoires cachés . Je préfère cette simplification:

Généralement pour exclure tous les chemins cachés (fichiers normaux, répertoires, etc.):

find <start-point> -path '*/.*' -prune -o <expression> -print

Par exemple, en utilisant votre répertoire de travail comme point de départ et -name '*some text*'comme expression:

find . -path '*/.*' -prune -o -name '*some text*' -print

Contrairement à ce que suggère la réponse de @ Flimm, il n’ya pas de fichiers cachés ni de répertoires cachés. L' -path '*/.*'expression est vraie pour tout chemin (fichiers réguliers, répertoires, etc.) qui a un .immédiatement après votre séparateur de fichiers, /. Donc, cette ligne va élaguer les fichiers cachés et les répertoires.

Autoriser les fichiers cachés tout en excluant les répertoires cachés est le cas qui nécessite un filtre supplémentaire. C’est là que vous incluez -type ddans l’expression à élaguer.

find <start-point> -type d -path '*/.*' -prune -o <expression> -print 

Par exemple:

find . -type d -path '*/.*' -prune -o -name '*some text*' -print

Dans ce cas, il -type d -path '*/.*'s’agit trueuniquement de répertoires et seuls les répertoires sont élagués.

De Novo
la source
0

finda des commutateurs logiques ordonnés tels que -andet -notvous pouvez les utiliser à votre avantage pour trouver un fichier correspondant avec deux règles comme ceci:

$ touch non_hidden_file.txt .hidden_file.txt somethings/.another_hidden_file.txt                                                 

$ find . -type f -name '*hidden_file*' -and \( -not -name ".*" \)                            
./non_hidden_file.txt

Comme vous pouvez le voir, findutilise deux règles -name '*hidden_file*'et -and \( -not -name ".*" \)de trouver les noms de fichiers qui correspondent à deux conditions - le nom de fichier avec hidden_fileen elle , mais sans point de premier plan. Notez les barres obliques devant les parenthèses - elles sont utilisées pour définir les parenthèses en tant findqu'arguments plutôt que pour définir un sous-shell (c'est ce que signifient les parenthèses sinon sans barres obliques)

Sergiy Kolodyazhnyy
la source
0
$ pwd
/home/victoria

$ find $(pwd) -maxdepth 1 -type f -not -path '*/\.*' | sort
/home/victoria/new
/home/victoria/new1
/home/victoria/new2
/home/victoria/new3
/home/victoria/new3.md
/home/victoria/new.md
/home/victoria/package.json
/home/victoria/Untitled Document 1
/home/victoria/Untitled Document 2

$ find . -maxdepth 1 -type f -not -path '*/\.*' | sed 's/^\.\///g' | sort
new
new1
new2
new3
new3.md
new.md
package.json
Untitled Document 1
Untitled Document 2

Remarques:

  • . : dossier en cours
  • supprimer -maxdepth 1pour rechercher récursivement
  • -type f: recherche de fichiers, pas de répertoires ( d)
  • -not -path '*/\.*' : ne pas revenir .hidden_files
  • sed 's/^\.\///g': supprimer le préfixe ./de la liste des résultats
Victoria Stuart
la source