2
votes

Comment trouver un fichier sur le $ PATH dans Bash?

L'utilitaire qui trouvera un programme sur le chemin mais qu'en est-il d'un fichier de données arbitraire?

Je dois chercher le mauvais truc mais je peux ' Je ne trouve aucun moyen de le faire avec un utilitaire standard alors j'ai pensé à écrire un petit script Bash pour le faire.

La variable d'environnement $ PATH est séparée par des deux-points, mais en essayant définir IFS = ':' puis parcourir les résultats ne fonctionne pas pour moi. Voici ce que j'ai jusqu'à présent:

IFS=':' DIRS=($PATH)
for d in $DIRS; do echo $d; done

À ce stade, il ne renvoie que la première entrée de mon chemin plutôt que toutes.

Réflexions ? S'il existe déjà une commande standard qui fait cela, il n'y a aucune raison d'écrire un script ...


1 commentaires

Les fichiers de données arbitraires ne devraient probablement pas être dans les listes de répertoires dans PATH .


4 Réponses :


6
votes

En utilisant ceci, en utilisant les extensions de paramètres bash et find:

find ${PATH//:/\/ } -name 'file'


5 commentaires

Supposons qu'il y ait un répertoire dans le PATH qui contient un espace. Ou un fichier dans un répertoire dans le PATH avec un espace dans le nom de fichier.


Vous ne développez pas non plus les fichiers dans la dernière entrée PATH.


Cette solution serait géniale si je pouvais utiliser find d'une manière qui recherche le $ PATH mais le remplacement des deux-points par des espaces ne fonctionnera pas


@GillesQuenot J'ai voté pour votre solution find parce que je l'aime mais cela ne fonctionnera pas quand il y a des espaces dans les répertoires qui sont dans $ PATH


Je n'utilise jamais d'espaces spécialement pour un répertoire PATH, et j'aime aussi ma solution ^^



2
votes

Pour trouver un fichier nommé $ name sur votre PATH en utilisant une boucle bash:

oldIFS=$IFS
IFS=:
for d in $PATH
do
    [ -f "$d/$name" ] && echo "Found $d/$name"
done
IFS=$oldIFS

Sur de nombreux systèmes, tels que debian , qui est juste un script shell et utilise une boucle très similaire. Jetez un œil à less / usr / bin / which .


0 commentaires

3
votes

Quelques choses se passent ici:

  1. IFS = ':' DIRS = ($ PATH)

    bash développera la variable avant de définir IFS et DIRS, il est donc trop tard d'ici là. Vous aurez besoin de quelque chose de fou comme

    for d in "${dirs[@]}" ...
    

- non, c'était faux. Tout d'abord, la variable $ PATH est développée, puis IFS est défini, puis l'élément DIRS est divisé en utilisant IFS car il n'est pas entre guillemets.

  1. pour d dans $ DIRS; faire echo $ d; terminé

    Pour parcourir tous les éléments d'un tableau, vous devez

    dirs=()
    while IFS= read -r -d: dir || [ "$dir" ]; do dirs+=("$dir"); done <<<"$PATH"
    

    Avec un tableau, $ DIRS est égal à $ {DIRS [0]} , c'est-à-dire la première entrée.

  2. N'utilisez pas de noms de variables ALLCAPS. Il est trop facile d'écraser une variable système cruciale.

  3. Citez vos variables à moins que vous ne sachiez exactement ce qui se passera si vous ne le faites pas.


0 commentaires

2
votes

L'erreur n'est pas avec l'affectation, mais avec le fait de ne pas boucler sur le tableau.

find "${dirs[@]}" -name "$desired_file_name"

fonctionne pour moi; ou plus succinctement

desired_file_name=$1  # or whatever
for dir in "${dirs[@]}"; do
    test -e "$dir/$desired_file_name" || continue
    echo "$0: found $dir/$desired_file_name" >&2
done

Comme vous l'avez découvert, $ dirs ne renvoie que le premier élément du tableau.

En fait parcourir ces répertoires à la recherche d'un fichier particulier, peut-être essayer

printf '%s\n' "${dirs[@]}"

Une autre approche est

IFS=: dirs=($PATH)
for dir in "${dirs[@]}"; do
    echo "$dir"
done

(vous devriez préférer les minuscules pour vos variables privées, j'ai donc changé DIRS en dirs . Moins de cris est bon aussi pour les yeux.)


1 commentaires

Huh, je suppose que je n'ai pas testé ce que j'ai écrit.