2008-09-24 9 views

Répondre

408

Voici comment faire avec les opérateurs # et% dans Bash.

$ x="/foo/fizzbuzz.bar" 
$ y=${x%.bar} 
$ echo ${y##*/} 
fizzbuzz 

${x%.bar} pourrait aussi être ${x%.*} pour enlever tout ce qui suit un point ou ${x%%.*} pour enlever tout ce qui suit le premier point.

Exemple:

$ x="/foo/fizzbuzz.bar.quux" 
$ y=${x%.*} 
$ echo $y 
/foo/fizzbuzz.bar 
$ y=${x%%.*} 
$ echo $y 
/foo/fizzbuzz 

La documentation se trouve dans le Bash manual. Recherchez ${parameter%word} et ${parameter%%word} section correspondante.

+0

J'ai fini par utiliser celui-ci parce que c'était le plus flexible et il y avait quelques autres choses similaires que je voulais faire aussi bien que cela a bien fonctionné. –

+0

C'est probablement la plus flexible de toutes les réponses postées, mais je pense que les réponses suggérant les commandes basename et dirname méritent aussi une certaine attention. Ils peuvent être juste l'astuce si vous n'avez pas besoin d'un autre motif de fantaisie. – mgadda

+3

Comment s'appelle-t-on $ {x% .bar}? Je voudrais en savoir plus à ce sujet. – Basil

170

regard sur la commande basename:

NAME=`basename /foo/fizzbuzz.bar .bar` 
+6

Probablement la plus simple de toutes les solutions actuellement proposées ... bien que j'utilise $ (...) au lieu de backticks. –

+6

Le plus simple mais ajoute une dépendance (pas énorme ou bizarre, j'avoue). Il doit également connaître le suffixe. –

+0

Et peut être utilisé pour enlever quelque chose de la fin, en fait, il ne fait que supprimer une chaîne de la fin. – Smar

12

façon bash pure:

~$ x="/foo/bar/fizzbuzz.bar.quux.zoom"; 
~$ y=${x/\/*\//}; 
~$ echo ${y/.*/}; 
fizzbuzz 

Cette fonctionnalité est expliquée man bash sous "Paramètres Expansion". Les manières non bash abondent: awk, perl, sed et ainsi de suite.

EDIT: Fonctionne avec des points dans le fichier et ne suffixes pas besoin de connaître le suffixe (extension), mais ne travail avec des points au nom lui-même.

3
perl -pe 's/\..*$//;s{^.*/}{}' 
7

Le nom de base et les fonctions de dirname sont ce que vous êtes après:

mystring=/foo/fizzbuzz.bar 
echo basename: $(basename $mystring) 
echo basename + remove .bar: $(basename $mystring .bar) 
echo dirname: $(dirname $mystring) 

a une sortie:

basename: fizzbuzz.bar 
basename + remove .bar: fizzbuzz 
dirname: /foo 
3

L'utilisation de basename suppose que vous connaissiez l'extension de fichier, n'est-ce pas?

Et je crois que les diverses suggestions d'expressions régulières ne font pas face à un nom de fichier contenant plus d'un "."

La suite semble prendre en compte les doubles points. Oh, et les noms de fichiers qui contiennent un «/» eux-mêmes (juste pour le plaisir)

Pour paraphraser Pascal, « Désolé, ce script est si longtemps. Je ne l'ai pas eu le temps de le rendre plus court »


    #!/usr/bin/perl 
    $fullname = $ARGV[0]; 
    ($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/; 
    ($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/; 
    print $basename . "\n"; 
+0

Ceci est agréable et robuste –

2

Si vous ne pouvez pas utiliser le nom de base comme suggéré dans d'autres publications, vous pouvez toujours utiliser sed. Voici un exemple (moche). Ce n'est pas le plus grand, mais cela fonctionne en extrayant la chaîne voulue et en remplaçant l'entrée par la chaîne voulue.

echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g' 

Ce qui vous permet d'obtenir la sortie

FizzBuzz

+0

Bien que ce soit la réponse à la question d'origine, cette commande est utile lorsque j'ai des lignes de chemins dans un fichier pour extraire des noms de base pour les imprimer à l'écran. –

0

Le basename fait ça, supprime le chemin. Il supprimera également le suffixe s'il est donné et s'il correspond au suffixe du fichier mais vous devrez connaître le suffixe à donner à la commande. Sinon, vous pouvez utiliser mv et comprendre ce que le nouveau nom devrait être d'une autre manière.

2

Attention à la solution Perl suggérée: elle supprime tout ce qui suit le premier point.

$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}' 
some 

Si vous voulez faire avec perl, cela fonctionne:

$ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}' 
some.file.with 

Mais si vous utilisez Bash, les solutions avec y=${x%.*} (ou basename "$x" .ext si vous connaissez l'extension) sont beaucoup plus simples.

10

En utilisant basename j'ai utilisé ce qui suit pour y parvenir:

for file in *; do 
    ext=${file##*.} 
    fname=`basename $file $ext` 

    # Do things with $fname 
done; 

Cela ne nécessite aucune connaissance a priori de l'extension de fichier et fonctionne même lorsque vous avez un nom de fichier qui a des points dans c'est le nom de fichier (en face de celui-ci est extension); Cependant, cela nécessite le programme basename, mais cela fait partie des coreutils GNU et devrait donc être livré avec n'importe quelle distribution.

+1

Excellente réponse! supprime l'extension d'une manière très propre, mais il ne supprime pas le. à la fin du nom de fichier. – metrix

+1

@metrix suffit d'ajouter le "." avant $ ext, par exemple: 'fname = \' basename $ file. $ ext \ '' –

28

bash pur, fait en deux opérations distinctes:

  1. Retirez le chemin d'un chemin cordes:

    path=/foo/bar/bim/baz/file.gif 
    
    file=${path##*/} 
    #$file is now 'file.gif' 
    
  2. supprimer l'extension d'un chemin de chaîne:

    base=${file%.*} 
    #${base} is now 'file'. 
    
1

Combinaison du t réponse op-évalué avec la réponse du deuxième top-rated pour obtenir le nom de fichier sans le chemin complet:

$ x="/foo/fizzbuzz.bar.quux" 
$ y=(`basename ${x%%.*}`) 
$ echo $y 
fizzbuzz 
0

Informations vous pouvez trouver dans Bash manual, recherchez ${parameter%word} et ${parameter%%word} dans la partie arrière section correspondant.

Questions connexes