web-dev-qa-db-fra.com

Comment vérifier si $ pwd est un sous-répertoire d'un chemin donné

Par exemple. vérifier si $PWD est un sous-répertoire de/home. En d'autres termes, je recherche une opération de chaîne Bash pour vérifier si une chaîne commence par une autre.

26
Tobias Kienzler

Si vous souhaitez tester de manière fiable si un répertoire est un sous-répertoire d'un autre, vous aurez besoin de plus d'un chèque de préfixe à chaîne. La réponse de Gilles décrit en détail comment faire ce test correctement.

Mais si vous voulez un chèque de préfixe de chaîne simple (peut-être que vous avez déjà normalisé vos chemins?), C'est un bon:

test "${PWD##/home/}" != "${PWD}"

Si $PWD commence par "/ home /", il est désactivé du côté gauche, ce qui signifie qu'il ne correspond pas au côté droit, alors "! =" retourne vrai.

28
Jander

Pour tester si une chaîne est un préfixe d'un autre, dans n'importe quel shell de style Bourne:

case $PWD/ in
  /home/*) echo "home sweet home";;
  *) echo "away from home";;
esac

Le même principe fonctionne pour un suffixe ou un test de sous-chaîne. Notez que dans case constructions, contrairement aux noms de fichier, * correspond à n'importe quel caractère, y compris un / ou une initiale ..

Dans les coquilles qui mettent en œuvre le [[ … ]] Syntaxe (c'est-à-dire Bash, ksh et ZSH), il peut être utilisé pour correspondre à une chaîne contre un motif. (Notez que le [ la commande ne peut tester que des chaînes pour l'égalité.)

if [[ $PWD/ = /home/* ]]; then …

Si vous testez spécifiquement si le répertoire actuel est sous /home, un simple test de sous-chaîne ne suffit pas, à cause de liens symboliques.

Si /home est un système de fichiers propre, testez si le répertoire actuel (.) est sur ce système de fichiers.

if [ "$(df -P . | awk 'NR==2 {print $6}')" = "/home" ]; then
  echo 'The current directory is on the /home filesystem'
fi

Si vous avez le NetBSD, OPENBSD OU GNU (I.E. Linux) readlink, vous pouvez utiliser readlink -f Pour désigner des liens symboliques d'un chemin.

case $(readlink -f .)/ in $(readlink -f /home)/*) …

Sinon, vous pouvez utiliser pwd pour afficher le répertoire actuel. Mais vous devez veiller à ne pas utiliser une coquille intégrée si votre shell piste cd _ commandes et conserve le nom que vous avez utilisé pour atteindre le répertoire plutôt que son emplacement "réel".

case $(pwd -P 2>/dev/null || env PWD= pwd)/ in
  "$(cd /home && { pwd -P 2>/dev/null || env PWD= pwd; })"/*) …

Version brute:

[ ${PWD:0:6} = "/home/" ]

A l'inconvénient que l'on doit compter les caractères d'abord et on ne peut pas remplacer /home/ par quelque chose de général comme $1.

éditer (merci @michael) pour la généralisation de comparer avec $VAR on peut utiliser

[ "${PWD:0:${#VAR}}" = $VAR ]
8
Tobias Kienzler

Je ne comprends pas trop la question, mais pour trouver le parent de $ pwd, do dirname $PWD. Pour trouver le parent du parent, exécutez dirname $(dirname $PWD), etc.

2
tshepang

Utilisation awk:

echo $PWD | awk -v h="/home" '$0 ~ h {print "MATCH"}'
1
dogbane

Hm, c'est pitié que [ n'a pas une option de test STRING1 starts with STRING2 état.

Vous pouvez essayer echo $PWD | grep '^$VAR', mais cela peut échouer de manière intéressante lorsque VAR contient des symboles spéciaux.

awk 's index fonction doit pouvoir faire l'affaire. Mais tout cela semble trop lourd pour une telle chose facile à tester.

0
alex

Si la partie recherchée du chemin est trouvée, je "vide" la variable:

[[ -z "${PWD//*\/home\/*/}" ]] && echo "toto"
0
user4177