Rechercher des fichiers dans plusieurs noms de dossiers

44

Je suis en train de lister tous les fichiers de dir1, dir2, dir3et dir4qui pourrait être n'importe où dans un sous - répertoire de mon cwdaide de la findcommande. J'ai essayé ce qui suit sans succès:

find . -type f -regextype posix-egrep -regex 'dir1/.+|dir2/.+|dir3/.+|dir4/.+'

J'ai essayé posix-extendedaussi. Comment puis-je lister ces fichiers?

Aaron
la source
trouver . -type f -regextype sed -regex ". * / dir [1-4] / [a-z0-9] *" .. réponse la plus courte à ce jour :) voir la réponse ci-dessous .. unix.stackexchange.com/a/390333 / 242983
alpha_989

Réponses:

59

Et si vous voulez rechercher trois dossiers nommés foo, baret bazpour tous les *.pyfichiers, utilisez cette commande:

find foo bar baz -name "*.py"

donc si vous voulez afficher des fichiers d' dir1 dir2 dir3utilisationfind dir1 dir2 dir3 -type f

essaye ça find . \( -name "dir1" -o -name "dir2" \) -exec ls '{}' \;

harish.venkat
la source
J'aurais dû clarifier. Je n'ai peut-être pas le chemin d'accès aux fichiers que je souhaite rechercher. Je sais seulement que ce sont des sous-répertoires du répertoire courant.
Aaron
utiliser ./dirau lieu dedir
harish.venkat
Le répertoire doit toujours être dans le cwd, cependant, il peut être inférieur de deux niveaux (par exemple ./path/to/dir1), auquel cas ./dir1il n’existerait pas.
Aaron
édité la réponse.
harish.venkat
8

Il est préférable d'utiliser la directive -path:

find .  \( -type f -and -path '*/dir1/*' -or -path '*/dir2/*' -or -path '*/dir3/*' -or -path '*/dir4/*' \)

Ce qui signifie: trouve tous les fichiers sous le répertoire courant où il y a 'dir1' ou 'dir2' ou 'dir3' ou 'dir4' dans le chemin.

Maintenance périodique
la source
Vous avez la parenthèse au mauvais endroit. Voir aussi -aet -opour l'équivalent standard de GNU -and/ -or.
Stéphane Chazelas
4

Juste pour que tout le monde sache. Ajouter .*/avant chaque dirproblème résolu, car regexil semble correspondre au chemin complet.

Aaron
la source
3

C'est ma première idée après avoir lu les réponses précédentes:

find . -type f -regextype posix-egrep -regex ".*/(dir1|dir2|dir3|dir4)/.+"

Cela prend en compte le fait que la regex doit correspondre à tout le nom du fichier, ce qui est plus facile à comprendre.

Ronin Tom
la source
2

Exemple de recherche rapide (!) De fichiers particuliers (access_log) dans plusieurs emplacements définis par le caractère générique (répertoire de base) et le répertoire de journaux général apache2, qui applique également le filtrage des noms afin d’exclure les journaux ssl et les anciens journaux gzippés. Ne répond pas directement à la question ici, mais pourrait être utile pour quelqu'un qui a trouvé ces instructions (comme moi).

find / \( -path "*var/log/apache2*" -o -path "*home/*/logs*" \) -type f  -name "*access_log" ! -name "*ssl*"

Faites attention aux espaces, spécialement près de \(et \).

À propos, je l’ai utilisé pour apachetop, pour trouver les sites Web les plus actifs sur mon serveur.

apachetop -d1 -s9 -p $(find / \( -path "*var/log/apache2*" -o -path "*home/*/logs*" \) -type f  -name "*access_log" ! -name "*ssl*" -print | sed 's/^/-f '/)
Kristjan Adojaan
la source
2

vous n'avez pas besoin de spécifier dir1 à dir4 par nom si vous utilisez regextype

find . -type f -regextype sed -regex ".*/dir[1-4]/[^/]*"
  • type f: trouver des fichiers pas des répertoires
  • regextype sed: utilise sed regextype
  • regex: recherche en utilisant regex dans tout le chemin
  • ".*/dir[1-4]/[a-z0-9]*":. * au début signifie n'importe quel nombre de caractères pouvant être de type (char / number / backslash (/) etc.); dir [1-4] signifie rechercher "dir" suivi d'un nombre compris entre 1 et 4; / [^ /] * indique que suivre dir1-4 omet tous les noms de chemin qui ont / dans, de sorte qu'il ne renvoie que les fichiers du répertoire dir1-dir4 et ignore les sous-répertoires éventuellement présents dans dir1-dir4.

a créé un répertoire pour le tester: https://github.com/alphaCTzo7G/stackexchange/tree/master/linux/findSolution04092017

alpha_989
la source
(1) Nous ne connaîtrons peut-être jamais la situation exacte d’Aaron ni ses exigences, mais d’autres réponses ont pris la décision prudente de disposer de quatre répertoires, dont les noms ne sont pas précisés. (Ils pourraient être red, green, blueet yellow, ou ils pourraient être John, Paul, Georgeet Ringo.) Votre réponse suppose qu'ils sont littéralement dir1 , dir2, dir3et dir4. … (Suite)
Scott le
(Suite)… (2) Pourquoi supposez-vous qu'Aaron ne veut pas chercher dans les sous-répertoires? Il semble dire qu'il le fait. (3) Pourquoi restreignez-vous la recherche aux fichiers dont le nom ne contient que des lettres minuscules et des chiffres (à l'exception des choses comme foo_bar, foo.txtet FOO)? (4) Pourquoi votre texte explique-t-il /[^/]*quand votre réponse ne l'utilise pas?
Scott
Bonjour Scott, c'est pour ton commentaire.
alpha_989
(1-3). il mentionne "J'essaie de lister tous les fichiers de dir1, dir2, dir3 et dir4 ", qui peuvent figurer n'importe où dans un sous-répertoire de mon cwd , ce qui signifie que dir1-dir4 peut se trouver n'importe où, mais il veut trouver le fichier à droite dans dir1-dir4. ofcourse, si ce n'est pas dir1-dir4, vous devez le changer pour les noms spécifiques en utilisant rouge \ | blue \ | green \ | etc.
alpha_989
4. faute de frappe là-bas ... j'ai utilisé [a-z0-9] * avant..alors rendu compte que [^ /] * est plus court et plus inclusif..pour le changer quand j'ai posté ceci. Merci pour vos commentaires soigneux.
alpha_989
0

Je sais que vous avez spécifié qu'en utilisant find, mais uniquement pour afficher d'autres options utilisables, vous pouvez utiliser xargs:

find . -type d | grep -E "dir1$|dir2$" | xargs ls  

find . -name "dir1" -or -name "dir2" | xargs ls

Vous pouvez avoir un fichier nommé "dossiers" qui contient quelque chose comme:

$ cat folders
dir1
dir2
dir3
dir4

Ensuite, vous pouvez faire quelque chose comme ceci:

$ cat folders | xargs -I % find . -type d -name % | xargs ls
./Documents/dir1:
file1  file2  file3  file4

./Documents/dir2:
file1  file2  file3  file4

./Documents/dir3:
file1  file2  file3  file4

./Documents/dir4:
file1  file2  file3  file4

xargs à mon avis, je me sens plus polyvalent que trouver -exec. Aussi, vous pouvez faire des trucs fous comme

$ cat << EOF | xargs -I {} find ~ -name "{}" | xargs ls
> dir1
> dir2
> dir3
> EOF
/home/user/Documents/dir1:
file1  file2  file3  file4

/home/user/Documents/dir2:
file1  file2  file3  file4

/home/user/Documents/dir3:
file1  file2  file3  file4
Cuauhtli
la source