Comment puis-je supprimer le suffixe de fichier et la partie path d'une chaîne de chemin dans Bash?
Étant donné un chemin de fichier de chaîne tel que " / foo / fizzbuzz.bar", comment utiliserais-je bash pour extraire uniquement la partie" fizzbuzz " de ladite chaîne?
13 réponses
Voici comment le faire avec les opérateurs # et % dans Bash.
$ x="/foo/fizzbuzz.bar"
$ y=${x%.bar}
$ echo ${y##*/}
fizzbuzz
${x%.bar}
peut aussi être ${x%.*}
pour tout supprimer après un point ou ${x%%.*}
pour tout supprimer après 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 manuel Bash . Recherchez ${parameter%word}
et ${parameter%%word}
section correspondant à la partie de fin.
Regardez la commande basename:
NAME=`basename /foo/fizzbuzz.bar .bar`
Pur bash, fait en deux opérations distinctes:
-
Supprime le chemin d'une chaîne de chemin:
path=/foo/bar/bim/baz/file.gif file=${path##*/} #$file is now 'file.gif'
-
Supprime l'extension d'une chaîne de chemin:
base=${file%.*} #${base} is now 'file'.
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 son nom de fichier (devant son extension); cela nécessite le programme basename
, mais cela fait partie de GNU coreutils, donc il devrait être livré avec n'importe quelle distribution.
Pur Bash façon:
~$ x="/foo/bar/fizzbuzz.bar.quux.zoom";
~$ y=${x/\/*\//};
~$ echo ${y/.*/};
fizzbuzz
Cette fonctionnalité est expliquée sur man bash sous "parameter Expansion". Les moyens non bash abondent: awk, perl, sed et ainsi de suite.
EDIT: fonctionne avec des points dans le fichier suffixes et n'a pas besoin de connaître le suffixe (extension), mais ne fonctionne pas avec des points dans le nom lui-même.
Les fonctions basename et dirname sont ce que vous recherchez:
mystring=/foo/fizzbuzz.bar
echo basename: $(basename $mystring)
echo basename + remove .bar: $(basename $mystring .bar)
echo dirname: $(dirname $mystring)
A la sortie:
basename: fizzbuzz.bar
basename + remove .bar: fizzbuzz
dirname: /foo
L'utilisation de basename
suppose que vous connaissez l'extension de fichier, n'est-ce pas?
Et je crois que les différentes suggestions d'expressions régulières ne font pas face à un nom de fichier contenant plus d'un "."
Ce qui suit semble faire face à des points doubles. Oh, et les noms de fichiers qui contiennent un " / " eux-mêmes (juste pour les coups de pied)
Pour paraphraser Pascal, " Désolé ce script est si long. Je n'ai pas eu le temps de le raccourcir "
#!/usr/bin/perl
$fullname = $ARGV[0];
($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
print $basename . "\n";
Si vous ne pouvez pas utiliser basename comme suggéré dans d'autres publications, vous pouvez toujours utiliser sed. Voici un (vilain) exemple. Ce n'est pas le plus grand, mais cela fonctionne en extrayant la chaîne désirée et en remplaçant l'entrée par la chaîne désirée.
echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'
Qui vous donnera la sortie
Fizzbuzz
Méfiez-vous de la solution Perl suggérée: elle supprime n'importe quoi après le premier point.
$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}'
some
Si vous voulez le 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.
Combinaison de la réponse la mieux notée avec la deuxième réponse la mieux notée pour obtenir le nom de fichier sans le chemin complet:
$ x="/foo/fizzbuzz.bar.quux"
$ y=(`basename ${x%%.*}`)
$ echo $y
fizzbuzz
Le nom de base fait cela, 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 pour donner à la commande. Sinon, vous pouvez utiliser mv et comprendre ce que le nouveau nom devrait être d'une autre manière.
Informations que vous pouvez trouver dans Bash manuel, recherchez ${parameter%word}
et ${parameter%%word}
dans la partie arrière de section de filtre.