390 votes

Extraire le nom de base d'un fichier sans le chemin et l'extension en bash

Avec des noms de fichiers comme ceux-ci :

/the/path/foo.txt
bar.txt

J'espère obtenir :

foo
bar

Pourquoi ça ne marche pas ?

#!/bin/bash

fullfile=$1
fname=$(basename $fullfile)
fbname=${fname%.*}
echo $fbname

Quelle est la bonne façon de procéder ?

1 votes

Ce code devrait fonctionner dans la plupart des cas tant que la valeur de $1 est en fait ce que vous pensez qu'il est. Cependant, elle est sujette à division des mots y expansion du nom de fichier en raison d'une mauvaise en citant .

0 votes

Closer @tripleee : ce n'est pas un doublon de Extraire le nom de fichier et l'extension en Bash . L'autre Q plus complexe exige que l'extension et le nom de fichier soient séparé . En fait, l'autre question est une élaboration de cette question plus fondamentale.

0 votes

@agc Les réponses semblent très similaires, mais la question la plus ancienne en comporte davantage. Pouvez-vous expliquer pourquoi vous pensez qu'elles devraient être séparées ?

732voto

ghostdog74 Points 86060

Vous n'avez pas besoin d'appeler le service externe basename . À la place, vous pouvez utiliser les commandes suivantes :

$ s=/the/path/foo.txt
$ echo "${s##*/}"
foo.txt
$ s=${s##*/}
$ echo "${s%.txt}"
foo
$ echo "${s%.*}"
foo

Notez que cette solution devrait fonctionner dans toutes les versions récentes ( après 2004 ) POSIX les coquilles conformes (par ex. bash , dash , ksh etc.).

Source : Langage de commande Shell 2.6.2 Expansion des paramètres

Plus d'informations sur les manipulations de chaînes de caractères dans bash : http://tldp.org/LDP/LG/issue18/bash.html

62 votes

Réponse fantastique... bash String Manipulations ( comme ${s##*/} ) sont expliqués ici linuxgazette.net/18/bash.html

6 votes

@chim avez-vous trouvé une référence mise à jour de votre lien ? Il est mort.

27 votes

@Droogans l'a trouvé après quelques recherches :) tldp.org/LDP/LG/issue18/bash.html je n'avais pas réalisé que j'avais 27 upvotes sur ce commentaire :)

330voto

Michael Aaron Safyan Points 45071

El nom de base a deux invocations différentes ; dans l'une, vous spécifiez seulement le chemin, dans ce cas il vous donne le dernier composant, tandis que dans l'autre vous donnez également un suffixe qu'il va supprimer. Vous pouvez donc simplifier le code de votre exemple en utilisant la deuxième invocation de basename. Faites également attention à citer correctement les choses :

fbname=$(basename "$1" .txt)
echo "$fbname"

16 votes

Existe-t-il un moyen de lui faire supprimer tout suffixe ?

3 votes

@handuel Malheureusement, basename ne prend pas en charge les caractères génériques. Fournir un second argument ne supprimera que la chaîne littérale exacte de la fin.

3 votes

Sur les machines avec un nom de base 8.4, cela fonctionne comme indiqué dans cette réponse, mais pour moi (avec un nom de base 8.22 de GNU coreutils) cela a fonctionné comme suit basename -s <extension> <filename> .

10voto

higuaro Points 7796

Voici une autre façon (plus complexe) d'obtenir le nom de fichier ou l'extension, en utilisant d'abord la fonction rev pour inverser le chemin du fichier, coupé à partir du premier . puis inverser le chemin du fichier à nouveau, comme ceci :

filename=`rev <<< "$1" | cut -d"." -f2- | rev`
fileext=`rev <<< "$1" | cut -d"." -f1 | rev`

0 votes

Je n'ai jamais vu ces équerres à triple angle <<< Les doohickeys c'est quoi ça ?

2 votes

Elles sont appelées "Here Strings" (plus d'infos) aquí ), en gros, il prend l'entrée comme une chaîne de caractères et la transmet à votre programme comme s'il lisait dans stdin.

2voto

Apelsin Points 178

Si vous voulez jouer avec les chemins de fichiers de Windows (sous Cygwin), vous pouvez aussi essayer ceci :

fname=${fullfile##*[/|\\]}

Cela permettra de tenir compte des séparateurs antislash lors de l'utilisation de BaSH sous Windows.

-15voto

Bandicoot Points 914

Utilisez la commande basename. Sa page de manuel est ici : http://unixhelp.ed.ac.uk/CGI/man-cgi?basename

9 votes

Il utilise basename mais ce n'est pas son problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X